Unverified Commit 8a86bca5 authored by Yossi Gottlieb's avatar Yossi Gottlieb Committed by GitHub
Browse files

Improve test suite to handle external servers better. (#9033)

This commit revives the improves the ability to run the test suite against
external servers, instead of launching and managing `redis-server` processes as
part of the test fixture.

This capability existed in the past, using the `--host` and `--port` options.
However, it was quite limited and mostly useful when running a specific tests.
Attempting to run larger chunks of the test suite experienced many issues:

* Many tests depend on being able to start and control `redis-server` themselves,
and there's no clear distinction between external server compatible and other
tests.
* Cluster mode is not supported (resulting with `CROSSSLOT` errors).

This PR cleans up many things and makes it possible to run the entire test suite
against an external server. It also provides more fine grained controls to
handle cases where the external server supports a subset of the Redis commands,
limited number of databases, cluster mode, etc.

The tests directory now contains a `README.md` file that describes how this
works.

This commit also includes additional cleanups and fixes:

* Tests can now be tagged.
* Tag-based selection is now unified across `start_server`, `tags` and `test`.
* More information is provided about skipped or ignored tests.
* Repeated patterns in tests have been extracted to common procedures, both at a
  global level and on a per-test file basis.
* Cleaned up some cases where test setup was based on a previous test executing
  (a major anti-pattern that repeats itself in many places).
* Cleaned up some cases where test teardown was not part of a test (in the
  future we should have dedicated teardown code that executes even when tests
  fail).
* Fixed some tests that were flaky running on external servers.
parent c396fd91
...@@ -5,7 +5,7 @@ proc log_file_matches {log pattern} { ...@@ -5,7 +5,7 @@ proc log_file_matches {log pattern} {
string match $pattern $content string match $pattern $content
} }
start_server {tags {"repl network"}} { start_server {tags {"repl network external:skip"}} {
set slave [srv 0 client] set slave [srv 0 client]
set slave_host [srv 0 host] set slave_host [srv 0 host]
set slave_port [srv 0 port] set slave_port [srv 0 port]
...@@ -51,7 +51,7 @@ start_server {tags {"repl network"}} { ...@@ -51,7 +51,7 @@ start_server {tags {"repl network"}} {
} }
} }
start_server {tags {"repl"}} { start_server {tags {"repl external:skip"}} {
set A [srv 0 client] set A [srv 0 client]
set A_host [srv 0 host] set A_host [srv 0 host]
set A_port [srv 0 port] set A_port [srv 0 port]
...@@ -187,7 +187,7 @@ start_server {tags {"repl"}} { ...@@ -187,7 +187,7 @@ start_server {tags {"repl"}} {
} }
} }
start_server {tags {"repl"}} { start_server {tags {"repl external:skip"}} {
r set mykey foo r set mykey foo
start_server {} { start_server {} {
...@@ -252,7 +252,7 @@ start_server {tags {"repl"}} { ...@@ -252,7 +252,7 @@ start_server {tags {"repl"}} {
foreach mdl {no yes} { foreach mdl {no yes} {
foreach sdl {disabled swapdb} { foreach sdl {disabled swapdb} {
start_server {tags {"repl"}} { start_server {tags {"repl external:skip"}} {
set master [srv 0 client] set master [srv 0 client]
$master config set repl-diskless-sync $mdl $master config set repl-diskless-sync $mdl
$master config set repl-diskless-sync-delay 1 $master config set repl-diskless-sync-delay 1
...@@ -340,7 +340,7 @@ foreach mdl {no yes} { ...@@ -340,7 +340,7 @@ foreach mdl {no yes} {
} }
} }
start_server {tags {"repl"}} { start_server {tags {"repl external:skip"}} {
set master [srv 0 client] set master [srv 0 client]
set master_host [srv 0 host] set master_host [srv 0 host]
set master_port [srv 0 port] set master_port [srv 0 port]
...@@ -448,7 +448,7 @@ test {slave fails full sync and diskless load swapdb recovers it} { ...@@ -448,7 +448,7 @@ test {slave fails full sync and diskless load swapdb recovers it} {
assert_equal [$slave dbsize] 2000 assert_equal [$slave dbsize] 2000
} }
} }
} } {} {external:skip}
test {diskless loading short read} { test {diskless loading short read} {
start_server {tags {"repl"}} { start_server {tags {"repl"}} {
...@@ -547,7 +547,7 @@ test {diskless loading short read} { ...@@ -547,7 +547,7 @@ test {diskless loading short read} {
$master config set rdb-key-save-delay 0 $master config set rdb-key-save-delay 0
} }
} }
} } {} {external:skip}
# get current stime and utime metrics for a thread (since it's creation) # get current stime and utime metrics for a thread (since it's creation)
proc get_cpu_metrics { statfile } { proc get_cpu_metrics { statfile } {
...@@ -581,7 +581,7 @@ proc compute_cpu_usage {start end} { ...@@ -581,7 +581,7 @@ proc compute_cpu_usage {start end} {
# test diskless rdb pipe with multiple replicas, which may drop half way # test diskless rdb pipe with multiple replicas, which may drop half way
start_server {tags {"repl"}} { start_server {tags {"repl external:skip"}} {
set master [srv 0 client] set master [srv 0 client]
$master config set repl-diskless-sync yes $master config set repl-diskless-sync yes
$master config set repl-diskless-sync-delay 1 $master config set repl-diskless-sync-delay 1
...@@ -769,7 +769,7 @@ test "diskless replication child being killed is collected" { ...@@ -769,7 +769,7 @@ test "diskless replication child being killed is collected" {
} }
} }
} }
} } {} {external:skip}
test "diskless replication read pipe cleanup" { test "diskless replication read pipe cleanup" {
# In diskless replication, we create a read pipe for the RDB, between the child and the parent. # In diskless replication, we create a read pipe for the RDB, between the child and the parent.
...@@ -808,7 +808,7 @@ test "diskless replication read pipe cleanup" { ...@@ -808,7 +808,7 @@ test "diskless replication read pipe cleanup" {
$master ping $master ping
} }
} }
} } {} {external:skip}
test {replicaof right after disconnection} { test {replicaof right after disconnection} {
# this is a rare race condition that was reproduced sporadically by the psync2 unit. # this is a rare race condition that was reproduced sporadically by the psync2 unit.
...@@ -860,7 +860,7 @@ test {replicaof right after disconnection} { ...@@ -860,7 +860,7 @@ test {replicaof right after disconnection} {
} }
} }
} }
} } {} {external:skip}
test {Kill rdb child process if its dumping RDB is not useful} { test {Kill rdb child process if its dumping RDB is not useful} {
start_server {tags {"repl"}} { start_server {tags {"repl"}} {
...@@ -925,4 +925,4 @@ test {Kill rdb child process if its dumping RDB is not useful} { ...@@ -925,4 +925,4 @@ test {Kill rdb child process if its dumping RDB is not useful} {
} }
} }
} }
} } {} {external:skip}
...@@ -158,14 +158,14 @@ proc server_is_up {host port retrynum} { ...@@ -158,14 +158,14 @@ proc server_is_up {host port retrynum} {
# there must be some intersection. If ::denytags are used, no intersection # there must be some intersection. If ::denytags are used, no intersection
# is allowed. Returns 1 if tags are acceptable or 0 otherwise, in which # is allowed. Returns 1 if tags are acceptable or 0 otherwise, in which
# case err_return names a return variable for the message to be logged. # case err_return names a return variable for the message to be logged.
proc tags_acceptable {err_return} { proc tags_acceptable {tags err_return} {
upvar $err_return err upvar $err_return err
# If tags are whitelisted, make sure there's match # If tags are whitelisted, make sure there's match
if {[llength $::allowtags] > 0} { if {[llength $::allowtags] > 0} {
set matched 0 set matched 0
foreach tag $::allowtags { foreach tag $::allowtags {
if {[lsearch $::tags $tag] >= 0} { if {[lsearch $tags $tag] >= 0} {
incr matched incr matched
} }
} }
...@@ -176,12 +176,27 @@ proc tags_acceptable {err_return} { ...@@ -176,12 +176,27 @@ proc tags_acceptable {err_return} {
} }
foreach tag $::denytags { foreach tag $::denytags {
if {[lsearch $::tags $tag] >= 0} { if {[lsearch $tags $tag] >= 0} {
set err "Tag: $tag denied" set err "Tag: $tag denied"
return 0 return 0
} }
} }
if {$::external && [lsearch $tags "external:skip"] >= 0} {
set err "Not supported on external server"
return 0
}
if {$::singledb && [lsearch $tags "singledb:skip"] >= 0} {
set err "Not supported on singledb"
return 0
}
if {$::cluster_mode && [lsearch $tags "cluster:skip"] >= 0} {
set err "Not supported in cluster mode"
return 0
}
return 1 return 1
} }
...@@ -191,7 +206,7 @@ proc tags {tags code} { ...@@ -191,7 +206,7 @@ proc tags {tags code} {
# we want to get rid of the quotes in order to have a proper list # we want to get rid of the quotes in order to have a proper list
set tags [string map { \" "" } $tags] set tags [string map { \" "" } $tags]
set ::tags [concat $::tags $tags] set ::tags [concat $::tags $tags]
if {![tags_acceptable err]} { if {![tags_acceptable $::tags err]} {
incr ::num_aborted incr ::num_aborted
send_data_packet $::test_server_fd ignore $err send_data_packet $::test_server_fd ignore $err
set ::tags [lrange $::tags 0 end-[llength $tags]] set ::tags [lrange $::tags 0 end-[llength $tags]]
...@@ -268,6 +283,68 @@ proc dump_server_log {srv} { ...@@ -268,6 +283,68 @@ proc dump_server_log {srv} {
puts "===== End of server log (pid $pid) =====\n" puts "===== End of server log (pid $pid) =====\n"
} }
proc run_external_server_test {code overrides} {
set srv {}
dict set srv "host" $::host
dict set srv "port" $::port
set client [redis $::host $::port 0 $::tls]
dict set srv "client" $client
if {!$::singledb} {
$client select 9
}
set config {}
dict set config "port" $::port
dict set srv "config" $config
# append the server to the stack
lappend ::servers $srv
if {[llength $::servers] > 1} {
if {$::verbose} {
puts "Notice: nested start_server statements in external server mode, test must be aware of that!"
}
}
r flushall
# store overrides
set saved_config {}
foreach {param val} $overrides {
dict set saved_config $param [lindex [r config get $param] 1]
r config set $param $val
# If we enable appendonly, wait for for rewrite to complete. This is
# required for tests that begin with a bg* command which will fail if
# the rewriteaof operation is not completed at this point.
if {$param == "appendonly" && $val == "yes"} {
waitForBgrewriteaof r
}
}
if {[catch {set retval [uplevel 2 $code]} error]} {
if {$::durable} {
set msg [string range $error 10 end]
lappend details $msg
lappend details $::errorInfo
lappend ::tests_failed $details
incr ::num_failed
send_data_packet $::test_server_fd err [join $details "\n"]
} else {
# Re-raise, let handler up the stack take care of this.
error $error $::errorInfo
}
}
# restore overrides
dict for {param val} $saved_config {
r config set $param $val
}
lpop ::servers
}
proc start_server {options {code undefined}} { proc start_server {options {code undefined}} {
# setup defaults # setup defaults
set baseconfig "default.conf" set baseconfig "default.conf"
...@@ -304,7 +381,7 @@ proc start_server {options {code undefined}} { ...@@ -304,7 +381,7 @@ proc start_server {options {code undefined}} {
} }
# We skip unwanted tags # We skip unwanted tags
if {![tags_acceptable err]} { if {![tags_acceptable $::tags err]} {
incr ::num_aborted incr ::num_aborted
send_data_packet $::test_server_fd ignore $err send_data_packet $::test_server_fd ignore $err
set ::tags [lrange $::tags 0 end-[llength $tags]] set ::tags [lrange $::tags 0 end-[llength $tags]]
...@@ -314,36 +391,8 @@ proc start_server {options {code undefined}} { ...@@ -314,36 +391,8 @@ proc start_server {options {code undefined}} {
# If we are running against an external server, we just push the # If we are running against an external server, we just push the
# host/port pair in the stack the first time # host/port pair in the stack the first time
if {$::external} { if {$::external} {
if {[llength $::servers] == 0} { run_external_server_test $code $overrides
set srv {}
dict set srv "host" $::host
dict set srv "port" $::port
set client [redis $::host $::port 0 $::tls]
dict set srv "client" $client
$client select 9
set config {}
dict set config "port" $::port
dict set srv "config" $config
# append the server to the stack
lappend ::servers $srv
}
r flushall
if {[catch {set retval [uplevel 1 $code]} error]} {
if {$::durable} {
set msg [string range $error 10 end]
lappend details $msg
lappend details $::errorInfo
lappend ::tests_failed $details
incr ::num_failed
send_data_packet $::test_server_fd err [join $details "\n"]
} else {
# Re-raise, let handler up the stack take care of this.
error $error $::errorInfo
}
}
set ::tags [lrange $::tags 0 end-[llength $tags]] set ::tags [lrange $::tags 0 end-[llength $tags]]
return return
} }
......
...@@ -85,6 +85,9 @@ proc assert_error {pattern code} { ...@@ -85,6 +85,9 @@ proc assert_error {pattern code} {
} }
proc assert_encoding {enc key} { proc assert_encoding {enc key} {
if {$::ignoreencoding} {
return
}
set dbg [r debug object $key] set dbg [r debug object $key]
assert_match "* encoding:$enc *" $dbg assert_match "* encoding:$enc *" $dbg
} }
...@@ -112,7 +115,7 @@ proc wait_for_condition {maxtries delay e _else_ elsescript} { ...@@ -112,7 +115,7 @@ proc wait_for_condition {maxtries delay e _else_ elsescript} {
} }
} }
proc test {name code {okpattern undefined} {options undefined}} { proc test {name code {okpattern undefined} {tags {}}} {
# abort if test name in skiptests # abort if test name in skiptests
if {[lsearch $::skiptests $name] >= 0} { if {[lsearch $::skiptests $name] >= 0} {
incr ::num_skipped incr ::num_skipped
...@@ -127,21 +130,12 @@ proc test {name code {okpattern undefined} {options undefined}} { ...@@ -127,21 +130,12 @@ proc test {name code {okpattern undefined} {options undefined}} {
return return
} }
# check if tagged with at least 1 tag to allow when there *is* a list set tags [concat $::tags $tags]
# of tags to allow, because default policy is to run everything if {![tags_acceptable $tags err]} {
if {[llength $::allowtags] > 0} {
set matched 0
foreach tag $::allowtags {
if {[lsearch $::tags $tag] >= 0} {
incr matched
}
}
if {$matched < 1} {
incr ::num_aborted incr ::num_aborted
send_data_packet $::test_server_fd ignore $name send_data_packet $::test_server_fd ignore "$name: $err"
return return
} }
}
incr ::num_tests incr ::num_tests
set details {} set details {}
......
...@@ -250,13 +250,19 @@ proc findKeyWithType {r type} { ...@@ -250,13 +250,19 @@ proc findKeyWithType {r type} {
} }
proc createComplexDataset {r ops {opt {}}} { proc createComplexDataset {r ops {opt {}}} {
set useexpire [expr {[lsearch -exact $opt useexpire] != -1}]
if {[lsearch -exact $opt usetag] != -1} {
set tag "{t}"
} else {
set tag ""
}
for {set j 0} {$j < $ops} {incr j} { for {set j 0} {$j < $ops} {incr j} {
set k [randomKey] set k [randomKey]$tag
set k2 [randomKey] set k2 [randomKey]$tag
set f [randomValue] set f [randomValue]
set v [randomValue] set v [randomValue]
if {[lsearch -exact $opt useexpire] != -1} { if {$useexpire} {
if {rand() < 0.1} { if {rand() < 0.1} {
{*}$r expire [randomKey] [randomInt 2] {*}$r expire [randomKey] [randomInt 2]
} }
...@@ -353,8 +359,15 @@ proc formatCommand {args} { ...@@ -353,8 +359,15 @@ proc formatCommand {args} {
proc csvdump r { proc csvdump r {
set o {} set o {}
for {set db 0} {$db < 16} {incr db} { if {$::singledb} {
set maxdb 1
} else {
set maxdb 16
}
for {set db 0} {$db < $maxdb} {incr db} {
if {!$::singledb} {
{*}$r select $db {*}$r select $db
}
foreach k [lsort [{*}$r keys *]] { foreach k [lsort [{*}$r keys *]] {
set type [{*}$r type $k] set type [{*}$r type $k]
append o [csvstring $db] , [csvstring $k] , [csvstring $type] , append o [csvstring $db] , [csvstring $k] , [csvstring $type] ,
...@@ -396,7 +409,9 @@ proc csvdump r { ...@@ -396,7 +409,9 @@ proc csvdump r {
} }
} }
} }
if {!$::singledb} {
{*}$r select 9 {*}$r select 9
}
return $o return $o
} }
...@@ -540,7 +555,7 @@ proc stop_bg_complex_data {handle} { ...@@ -540,7 +555,7 @@ proc stop_bg_complex_data {handle} {
catch {exec /bin/kill -9 $handle} catch {exec /bin/kill -9 $handle}
} }
proc populate {num prefix size} { proc populate {num {prefix key:} {size 3}} {
set rd [redis_deferring_client] set rd [redis_deferring_client]
for {set j 0} {$j < $num} {incr j} { for {set j 0} {$j < $num} {incr j} {
$rd set $prefix$j [string repeat A $size] $rd set $prefix$j [string repeat A $size]
...@@ -777,6 +792,30 @@ proc punsubscribe {client {channels {}}} { ...@@ -777,6 +792,30 @@ proc punsubscribe {client {channels {}}} {
consume_subscribe_messages $client punsubscribe $channels consume_subscribe_messages $client punsubscribe $channels
} }
proc debug_digest_value {key} {
if {!$::ignoredigest} {
r debug digest-value $key
} else {
return "dummy-digest-value"
}
}
proc wait_for_blocked_client {} {
wait_for_condition 50 100 {
[s blocked_clients] ne 0
} else {
fail "no blocked clients"
}
}
proc wait_for_blocked_clients_count {count {maxtries 100} {delay 10}} {
wait_for_condition $maxtries $delay {
[s blocked_clients] == $count
} else {
fail "Timeout waiting for blocked clients"
}
}
proc read_from_aof {fp} { proc read_from_aof {fp} {
# Input fp is a blocking binary file descriptor of an opened AOF file. # Input fp is a blocking binary file descriptor of an opened AOF file.
if {[gets $fp count] == -1} return "" if {[gets $fp count] == -1} return ""
...@@ -802,3 +841,27 @@ proc assert_aof_content {aof_path patterns} { ...@@ -802,3 +841,27 @@ proc assert_aof_content {aof_path patterns} {
assert_match [lindex $patterns $j] [read_from_aof $fp] assert_match [lindex $patterns $j] [read_from_aof $fp]
} }
} }
proc config_set {param value {options {}}} {
set mayfail 0
foreach option $options {
switch $option {
"mayfail" {
set mayfail 1
}
default {
error "Unknown option $option"
}
}
}
if {[catch {r config set $param $value} err]} {
if {!$mayfail} {
error $err
} else {
if {$::verbose} {
puts "Ignoring CONFIG SET $param $value failure: $err"
}
}
}
}
...@@ -114,6 +114,10 @@ set ::stop_on_failure 0 ...@@ -114,6 +114,10 @@ set ::stop_on_failure 0
set ::dump_logs 0 set ::dump_logs 0
set ::loop 0 set ::loop 0
set ::tlsdir "tests/tls" set ::tlsdir "tests/tls"
set ::singledb 0
set ::cluster_mode 0
set ::ignoreencoding 0
set ::ignoredigest 0
# Set to 1 when we are running in client mode. The Redis test uses a # Set to 1 when we are running in client mode. The Redis test uses a
# server-client model to run tests simultaneously. The server instance # server-client model to run tests simultaneously. The server instance
...@@ -191,7 +195,7 @@ proc reconnect {args} { ...@@ -191,7 +195,7 @@ proc reconnect {args} {
dict set srv "client" $client dict set srv "client" $client
# select the right db when we don't have to authenticate # select the right db when we don't have to authenticate
if {![dict exists $config "requirepass"]} { if {![dict exists $config "requirepass"] && !$::singledb} {
$client select 9 $client select 9
} }
...@@ -210,8 +214,14 @@ proc redis_deferring_client {args} { ...@@ -210,8 +214,14 @@ proc redis_deferring_client {args} {
set client [redis [srv $level "host"] [srv $level "port"] 1 $::tls] set client [redis [srv $level "host"] [srv $level "port"] 1 $::tls]
# select the right db and read the response (OK) # select the right db and read the response (OK)
if {!$::singledb} {
$client select 9 $client select 9
$client read $client read
} else {
# For timing/symmetry with the above select
$client ping
$client read
}
return $client return $client
} }
...@@ -225,8 +235,13 @@ proc redis_client {args} { ...@@ -225,8 +235,13 @@ proc redis_client {args} {
# create client that defers reading reply # create client that defers reading reply
set client [redis [srv $level "host"] [srv $level "port"] 0 $::tls] set client [redis [srv $level "host"] [srv $level "port"] 0 $::tls]
# select the right db and read the response (OK) # select the right db and read the response (OK), or at least ping
# the server if we're in a singledb mode.
if {$::singledb} {
$client ping
} else {
$client select 9 $client select 9
}
return $client return $client
} }
...@@ -552,6 +567,7 @@ proc print_help_screen {} { ...@@ -552,6 +567,7 @@ proc print_help_screen {} {
"--config <k> <v> Extra config file argument." "--config <k> <v> Extra config file argument."
"--skipfile <file> Name of a file containing test names that should be skipped (one per line)." "--skipfile <file> Name of a file containing test names that should be skipped (one per line)."
"--skiptest <name> Name of a file containing test names that should be skipped (one per line)." "--skiptest <name> Name of a file containing test names that should be skipped (one per line)."
"--tags <tags> Run only tests having specified tags or not having '-' prefixed tags."
"--dont-clean Don't delete redis log files after the run." "--dont-clean Don't delete redis log files after the run."
"--no-latency Skip latency measurements and validation by some tests." "--no-latency Skip latency measurements and validation by some tests."
"--stop Blocks once the first test fails." "--stop Blocks once the first test fails."
...@@ -563,6 +579,10 @@ proc print_help_screen {} { ...@@ -563,6 +579,10 @@ proc print_help_screen {} {
"--port <port> TCP port to use against external host." "--port <port> TCP port to use against external host."
"--baseport <port> Initial port number for spawned redis servers." "--baseport <port> Initial port number for spawned redis servers."
"--portcount <num> Port range for spawned redis servers." "--portcount <num> Port range for spawned redis servers."
"--singledb Use a single database, avoid SELECT."
"--cluster-mode Run tests in cluster protocol compatible mode."
"--ignore-encoding Don't validate object encoding."
"--ignore-digest Don't use debug digest validations."
"--help Print this help screen." "--help Print this help screen."
} "\n"] } "\n"]
} }
...@@ -669,6 +689,15 @@ for {set j 0} {$j < [llength $argv]} {incr j} { ...@@ -669,6 +689,15 @@ for {set j 0} {$j < [llength $argv]} {incr j} {
} elseif {$opt eq {--timeout}} { } elseif {$opt eq {--timeout}} {
set ::timeout $arg set ::timeout $arg
incr j incr j
} elseif {$opt eq {--singledb}} {
set ::singledb 1
} elseif {$opt eq {--cluster-mode}} {
set ::cluster_mode 1
set ::singledb 1
} elseif {$opt eq {--ignore-encoding}} {
set ::ignoreencoding 1
} elseif {$opt eq {--ignore-digest}} {
set ::ignoredigest 1
} elseif {$opt eq {--help}} { } elseif {$opt eq {--help}} {
print_help_screen print_help_screen
exit 0 exit 0
...@@ -782,6 +811,7 @@ proc assert_replication_stream {s patterns} { ...@@ -782,6 +811,7 @@ proc assert_replication_stream {s patterns} {
proc close_replication_stream {s} { proc close_replication_stream {s} {
close $s close $s
r config set repl-ping-replica-period 10 r config set repl-ping-replica-period 10
return
} }
# With the parallel test running multiple Redis instances at the same time # With the parallel test running multiple Redis instances at the same time
......
start_server {tags {"acl"}} { start_server {tags {"acl external:skip"}} {
test {Connections start with the default user} { test {Connections start with the default user} {
r ACL WHOAMI r ACL WHOAMI
} {default} } {default}
...@@ -482,7 +482,7 @@ start_server {tags {"acl"}} { ...@@ -482,7 +482,7 @@ start_server {tags {"acl"}} {
set server_path [tmpdir "server.acl"] set server_path [tmpdir "server.acl"]
exec cp -f tests/assets/user.acl $server_path 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"] tags [list "external:skip"]] {
# 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 # user default on nopass ~* +@all
...@@ -570,7 +570,7 @@ start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"]] { ...@@ -570,7 +570,7 @@ start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"]] {
set server_path [tmpdir "resetchannels.acl"] set server_path [tmpdir "resetchannels.acl"]
exec cp -f tests/assets/nodefaultuser.acl $server_path exec cp -f tests/assets/nodefaultuser.acl $server_path
exec cp -f tests/assets/default.conf $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"]] { start_server [list overrides [list "dir" $server_path "acl-pubsub-default" "resetchannels" "aclfile" "nodefaultuser.acl"] tags [list "external:skip"]] {
test {Default user has access to all channels irrespective of flag} { test {Default user has access to all channels irrespective of flag} {
set channelinfo [dict get [r ACL getuser default] channels] set channelinfo [dict get [r ACL getuser default] channels]
...@@ -609,7 +609,7 @@ start_server [list overrides [list "dir" $server_path "acl-pubsub-default" "rese ...@@ -609,7 +609,7 @@ start_server [list overrides [list "dir" $server_path "acl-pubsub-default" "rese
set server_path [tmpdir "resetchannels.acl"] set server_path [tmpdir "resetchannels.acl"]
exec cp -f tests/assets/nodefaultuser.acl $server_path exec cp -f tests/assets/nodefaultuser.acl $server_path
exec cp -f tests/assets/default.conf $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"]] { start_server [list overrides [list "dir" $server_path "acl-pubsub-default" "resetchannels" "aclfile" "nodefaultuser.acl"] tags [list "external:skip"]] {
test {Only default user has access to all channels irrespective of flag} { test {Only default user has access to all channels irrespective of flag} {
set channelinfo [dict get [r ACL getuser default] channels] set channelinfo [dict get [r ACL getuser default] channels]
...@@ -620,7 +620,7 @@ start_server [list overrides [list "dir" $server_path "acl-pubsub-default" "rese ...@@ -620,7 +620,7 @@ start_server [list overrides [list "dir" $server_path "acl-pubsub-default" "rese
} }
start_server {overrides {user "default on nopass ~* +@all"}} { start_server {overrides {user "default on nopass ~* +@all"} tags {"external:skip"}} {
test {default: load from config file, can access any channels} { test {default: load from config file, can access any channels} {
r SUBSCRIBE foo r SUBSCRIBE foo
r PSUBSCRIBE bar* r PSUBSCRIBE bar*
......
start_server {tags {"aofrw"}} { start_server {tags {"aofrw external:skip"}} {
# Enable the AOF # Enable the AOF
r config set appendonly yes r config set appendonly yes
r config set auto-aof-rewrite-percentage 0 ; # Disable auto-rewrite. r config set auto-aof-rewrite-percentage 0 ; # Disable auto-rewrite.
...@@ -57,7 +57,7 @@ start_server {tags {"aofrw"}} { ...@@ -57,7 +57,7 @@ start_server {tags {"aofrw"}} {
} }
} }
start_server {tags {"aofrw"} overrides {aof-use-rdb-preamble no}} { start_server {tags {"aofrw external:skip"} overrides {aof-use-rdb-preamble no}} {
test {Turning off AOF kills the background writing child if any} { test {Turning off AOF kills the background writing child if any} {
r config set appendonly yes r config set appendonly yes
waitForBgrewriteaof r waitForBgrewriteaof r
......
start_server {tags {"auth"}} { start_server {tags {"auth external:skip"}} {
test {AUTH fails if there is no password configured server side} { test {AUTH fails if there is no password configured server side} {
catch {r auth foo} err catch {r auth foo} err
set _ $err set _ $err
} {ERR*any password*} } {ERR*any password*}
} }
start_server {tags {"auth"} overrides {requirepass foobar}} { start_server {tags {"auth external:skip"} overrides {requirepass foobar}} {
test {AUTH fails when a wrong password is given} { test {AUTH fails when a wrong password is given} {
catch {r auth wrong!} err catch {r auth wrong!} err
set _ $err set _ $err
...@@ -26,7 +26,7 @@ start_server {tags {"auth"} overrides {requirepass foobar}} { ...@@ -26,7 +26,7 @@ start_server {tags {"auth"} overrides {requirepass foobar}} {
} {101} } {101}
} }
start_server {tags {"auth_binary_password"}} { start_server {tags {"auth_binary_password external:skip"}} {
test {AUTH fails when binary password is wrong} { test {AUTH fails when binary password is wrong} {
r config set requirepass "abc\x00def" r config set requirepass "abc\x00def"
catch {r auth abc} err catch {r auth abc} err
......
...@@ -200,7 +200,7 @@ start_server {tags {"bitops"}} { ...@@ -200,7 +200,7 @@ start_server {tags {"bitops"}} {
} }
} }
start_server {tags {"repl"}} { start_server {tags {"repl external:skip"}} {
start_server {} { start_server {} {
set master [srv -1 client] set master [srv -1 client]
set master_host [srv -1 host] set master_host [srv -1 host]
......
...@@ -121,15 +121,15 @@ start_server {tags {"bitops"}} { ...@@ -121,15 +121,15 @@ start_server {tags {"bitops"}} {
} {74} } {74}
test {BITOP NOT (empty string)} { test {BITOP NOT (empty string)} {
r set s "" r set s{t} ""
r bitop not dest s r bitop not dest{t} s{t}
r get dest r get dest{t}
} {} } {}
test {BITOP NOT (known string)} { test {BITOP NOT (known string)} {
r set s "\xaa\x00\xff\x55" r set s{t} "\xaa\x00\xff\x55"
r bitop not dest s r bitop not dest{t} s{t}
r get dest r get dest{t}
} "\x55\xff\x00\xaa" } "\x55\xff\x00\xaa"
test {BITOP where dest and target are the same key} { test {BITOP where dest and target are the same key} {
...@@ -139,28 +139,28 @@ start_server {tags {"bitops"}} { ...@@ -139,28 +139,28 @@ start_server {tags {"bitops"}} {
} "\x55\xff\x00\xaa" } "\x55\xff\x00\xaa"
test {BITOP AND|OR|XOR don't change the string with single input key} { test {BITOP AND|OR|XOR don't change the string with single input key} {
r set a "\x01\x02\xff" r set a{t} "\x01\x02\xff"
r bitop and res1 a r bitop and res1{t} a{t}
r bitop or res2 a r bitop or res2{t} a{t}
r bitop xor res3 a r bitop xor res3{t} a{t}
list [r get res1] [r get res2] [r get res3] list [r get res1{t}] [r get res2{t}] [r get res3{t}]
} [list "\x01\x02\xff" "\x01\x02\xff" "\x01\x02\xff"] } [list "\x01\x02\xff" "\x01\x02\xff" "\x01\x02\xff"]
test {BITOP missing key is considered a stream of zero} { test {BITOP missing key is considered a stream of zero} {
r set a "\x01\x02\xff" r set a{t} "\x01\x02\xff"
r bitop and res1 no-suck-key a r bitop and res1{t} no-suck-key{t} a{t}
r bitop or res2 no-suck-key a no-such-key r bitop or res2{t} no-suck-key{t} a{t} no-such-key{t}
r bitop xor res3 no-such-key a r bitop xor res3{t} no-such-key{t} a{t}
list [r get res1] [r get res2] [r get res3] list [r get res1{t}] [r get res2{t}] [r get res3{t}]
} [list "\x00\x00\x00" "\x01\x02\xff" "\x01\x02\xff"] } [list "\x00\x00\x00" "\x01\x02\xff" "\x01\x02\xff"]
test {BITOP shorter keys are zero-padded to the key with max length} { test {BITOP shorter keys are zero-padded to the key with max length} {
r set a "\x01\x02\xff\xff" r set a{t} "\x01\x02\xff\xff"
r set b "\x01\x02\xff" r set b{t} "\x01\x02\xff"
r bitop and res1 a b r bitop and res1{t} a{t} b{t}
r bitop or res2 a b r bitop or res2{t} a{t} b{t}
r bitop xor res3 a b r bitop xor res3{t} a{t} b{t}
list [r get res1] [r get res2] [r get res3] list [r get res1{t}] [r get res2{t}] [r get res3{t}]
} [list "\x01\x02\xff\x00" "\x01\x02\xff\xff" "\x00\x00\x00\xff"] } [list "\x01\x02\xff\x00" "\x01\x02\xff\xff" "\x00\x00\x00\xff"]
foreach op {and or xor} { foreach op {and or xor} {
...@@ -173,11 +173,11 @@ start_server {tags {"bitops"}} { ...@@ -173,11 +173,11 @@ start_server {tags {"bitops"}} {
for {set j 0} {$j < $numvec} {incr j} { for {set j 0} {$j < $numvec} {incr j} {
set str [randstring 0 1000] set str [randstring 0 1000]
lappend vec $str lappend vec $str
lappend veckeys vector_$j lappend veckeys vector_$j{t}
r set vector_$j $str r set vector_$j{t} $str
} }
r bitop $op target {*}$veckeys r bitop $op target{t} {*}$veckeys
assert_equal [r get target] [simulate_bit_op $op {*}$vec] assert_equal [r get target{t}] [simulate_bit_op $op {*}$vec]
} }
} }
} }
...@@ -186,32 +186,32 @@ start_server {tags {"bitops"}} { ...@@ -186,32 +186,32 @@ start_server {tags {"bitops"}} {
for {set i 0} {$i < 10} {incr i} { for {set i 0} {$i < 10} {incr i} {
r flushall r flushall
set str [randstring 0 1000] set str [randstring 0 1000]
r set str $str r set str{t} $str
r bitop not target str r bitop not target{t} str{t}
assert_equal [r get target] [simulate_bit_op not $str] assert_equal [r get target{t}] [simulate_bit_op not $str]
} }
} }
test {BITOP with integer encoded source objects} { test {BITOP with integer encoded source objects} {
r set a 1 r set a{t} 1
r set b 2 r set b{t} 2
r bitop xor dest a b a r bitop xor dest{t} a{t} b{t} a{t}
r get dest r get dest{t}
} {2} } {2}
test {BITOP with non string source key} { test {BITOP with non string source key} {
r del c r del c{t}
r set a 1 r set a{t} 1
r set b 2 r set b{t} 2
r lpush c foo r lpush c{t} foo
catch {r bitop xor dest a b c d} e catch {r bitop xor dest{t} a{t} b{t} c{t} d{t}} e
set e set e
} {WRONGTYPE*} } {WRONGTYPE*}
test {BITOP with empty string after non empty string (issue #529)} { test {BITOP with empty string after non empty string (issue #529)} {
r flushdb r flushdb
r set a "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" r set a{t} "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
r bitop or x a b r bitop or x{t} a{t} b{t}
} {32} } {32}
test {BITPOS bit=0 with empty key returns 0} { test {BITPOS bit=0 with empty key returns 0} {
......
...@@ -46,7 +46,7 @@ start_server {tags {"dump"}} { ...@@ -46,7 +46,7 @@ start_server {tags {"dump"}} {
catch {r debug object foo} e catch {r debug object foo} e
r debug set-active-expire 1 r debug set-active-expire 1
set e set e
} {ERR no such key} } {ERR no such key} {needs:debug}
test {RESTORE can set LRU} { test {RESTORE can set LRU} {
r set foo bar r set foo bar
...@@ -56,8 +56,9 @@ start_server {tags {"dump"}} { ...@@ -56,8 +56,9 @@ start_server {tags {"dump"}} {
r restore foo 0 $encoded idletime 1000 r restore foo 0 $encoded idletime 1000
set idle [r object idletime foo] set idle [r object idletime foo]
assert {$idle >= 1000 && $idle <= 1010} assert {$idle >= 1000 && $idle <= 1010}
r get foo assert_equal [r get foo] {bar}
} {bar} r config set maxmemory-policy noeviction
} {OK} {needs:config-maxmemory}
test {RESTORE can set LFU} { test {RESTORE can set LFU} {
r set foo bar r set foo bar
...@@ -68,7 +69,9 @@ start_server {tags {"dump"}} { ...@@ -68,7 +69,9 @@ start_server {tags {"dump"}} {
set freq [r object freq foo] set freq [r object freq foo]
assert {$freq == 100} assert {$freq == 100}
r get foo r get foo
} {bar} assert_equal [r get foo] {bar}
r config set maxmemory-policy noeviction
} {OK} {needs:config-maxmemory}
test {RESTORE returns an error of the key already exists} { test {RESTORE returns an error of the key already exists} {
r set foo bar r set foo bar
...@@ -111,7 +114,7 @@ start_server {tags {"dump"}} { ...@@ -111,7 +114,7 @@ start_server {tags {"dump"}} {
r -1 migrate $second_host $second_port key 9 1000 r -1 migrate $second_host $second_port key 9 1000
assert_match {*migrate_cached_sockets:1*} [r -1 info] assert_match {*migrate_cached_sockets:1*} [r -1 info]
} }
} } {} {external:skip}
test {MIGRATE cached connections are released after some time} { test {MIGRATE cached connections are released after some time} {
after 15000 after 15000
...@@ -135,7 +138,7 @@ start_server {tags {"dump"}} { ...@@ -135,7 +138,7 @@ start_server {tags {"dump"}} {
assert {[$second get key] eq {Some Value}} assert {[$second get key] eq {Some Value}}
assert {[$second ttl key] == -1} assert {[$second ttl key] == -1}
} }
} } {} {external:skip}
test {MIGRATE is able to copy a key between two instances} { test {MIGRATE is able to copy a key between two instances} {
set first [srv 0 client] set first [srv 0 client]
...@@ -154,7 +157,7 @@ start_server {tags {"dump"}} { ...@@ -154,7 +157,7 @@ start_server {tags {"dump"}} {
assert {[$second exists list] == 1} assert {[$second exists list] == 1}
assert {[$first lrange list 0 -1] eq [$second lrange list 0 -1]} assert {[$first lrange list 0 -1] eq [$second lrange list 0 -1]}
} }
} } {} {external:skip}
test {MIGRATE will not overwrite existing keys, unless REPLACE is used} { test {MIGRATE will not overwrite existing keys, unless REPLACE is used} {
set first [srv 0 client] set first [srv 0 client]
...@@ -176,7 +179,7 @@ start_server {tags {"dump"}} { ...@@ -176,7 +179,7 @@ start_server {tags {"dump"}} {
assert {[$second exists list] == 1} assert {[$second exists list] == 1}
assert {[$first lrange list 0 -1] eq [$second lrange list 0 -1]} assert {[$first lrange list 0 -1] eq [$second lrange list 0 -1]}
} }
} } {} {external:skip}
test {MIGRATE propagates TTL correctly} { test {MIGRATE propagates TTL correctly} {
set first [srv 0 client] set first [srv 0 client]
...@@ -196,7 +199,7 @@ start_server {tags {"dump"}} { ...@@ -196,7 +199,7 @@ start_server {tags {"dump"}} {
assert {[$second get key] eq {Some Value}} assert {[$second get key] eq {Some Value}}
assert {[$second ttl key] >= 7 && [$second ttl key] <= 10} assert {[$second ttl key] >= 7 && [$second ttl key] <= 10}
} }
} } {} {external:skip}
test {MIGRATE can correctly transfer large values} { test {MIGRATE can correctly transfer large values} {
set first [srv 0 client] set first [srv 0 client]
...@@ -221,7 +224,7 @@ start_server {tags {"dump"}} { ...@@ -221,7 +224,7 @@ start_server {tags {"dump"}} {
assert {[$second ttl key] == -1} assert {[$second ttl key] == -1}
assert {[$second llen key] == 40000*20} assert {[$second llen key] == 40000*20}
} }
} } {} {external:skip}
test {MIGRATE can correctly transfer hashes} { test {MIGRATE can correctly transfer hashes} {
set first [srv 0 client] set first [srv 0 client]
...@@ -241,7 +244,7 @@ start_server {tags {"dump"}} { ...@@ -241,7 +244,7 @@ start_server {tags {"dump"}} {
assert {[$second exists key] == 1} assert {[$second exists key] == 1}
assert {[$second ttl key] == -1} assert {[$second ttl key] == -1}
} }
} } {} {external:skip}
test {MIGRATE timeout actually works} { test {MIGRATE timeout actually works} {
set first [srv 0 client] set first [srv 0 client]
...@@ -260,7 +263,7 @@ start_server {tags {"dump"}} { ...@@ -260,7 +263,7 @@ start_server {tags {"dump"}} {
catch {r -1 migrate $second_host $second_port key 9 500} e catch {r -1 migrate $second_host $second_port key 9 500} e
assert_match {IOERR*} $e assert_match {IOERR*} $e
} }
} } {} {external:skip}
test {MIGRATE can migrate multiple keys at once} { test {MIGRATE can migrate multiple keys at once} {
set first [srv 0 client] set first [srv 0 client]
...@@ -283,12 +286,12 @@ start_server {tags {"dump"}} { ...@@ -283,12 +286,12 @@ start_server {tags {"dump"}} {
assert {[$second get key2] eq {v2}} assert {[$second get key2] eq {v2}}
assert {[$second get key3] eq {v3}} assert {[$second get key3] eq {v3}}
} }
} } {} {external:skip}
test {MIGRATE with multiple keys must have empty key arg} { test {MIGRATE with multiple keys must have empty key arg} {
catch {r MIGRATE 127.0.0.1 6379 NotEmpty 9 5000 keys a b c} e catch {r MIGRATE 127.0.0.1 6379 NotEmpty 9 5000 keys a b c} e
set e set e
} {*empty string*} } {*empty string*} {external:skip}
test {MIGRATE with multiple keys migrate just existing ones} { test {MIGRATE with multiple keys migrate just existing ones} {
set first [srv 0 client] set first [srv 0 client]
...@@ -314,7 +317,7 @@ start_server {tags {"dump"}} { ...@@ -314,7 +317,7 @@ start_server {tags {"dump"}} {
assert {[$second get key2] eq {v2}} assert {[$second get key2] eq {v2}}
assert {[$second get key3] eq {v3}} assert {[$second get key3] eq {v3}}
} }
} } {} {external:skip}
test {MIGRATE with multiple keys: stress command rewriting} { test {MIGRATE with multiple keys: stress command rewriting} {
set first [srv 0 client] set first [srv 0 client]
...@@ -330,7 +333,7 @@ start_server {tags {"dump"}} { ...@@ -330,7 +333,7 @@ start_server {tags {"dump"}} {
assert {[$first dbsize] == 0} assert {[$first dbsize] == 0}
assert {[$second dbsize] == 15} assert {[$second dbsize] == 15}
} }
} } {} {external:skip}
test {MIGRATE with multiple keys: delete just ack keys} { test {MIGRATE with multiple keys: delete just ack keys} {
set first [srv 0 client] set first [srv 0 client]
...@@ -350,7 +353,7 @@ start_server {tags {"dump"}} { ...@@ -350,7 +353,7 @@ start_server {tags {"dump"}} {
assert {[$first exists c] == 1} assert {[$first exists c] == 1}
assert {[$first exists d] == 1} assert {[$first exists d] == 1}
} }
} } {} {external:skip}
test {MIGRATE AUTH: correct and wrong password cases} { test {MIGRATE AUTH: correct and wrong password cases} {
set first [srv 0 client] set first [srv 0 client]
...@@ -375,5 +378,5 @@ start_server {tags {"dump"}} { ...@@ -375,5 +378,5 @@ start_server {tags {"dump"}} {
catch {r -1 migrate $second_host $second_port list 9 5000 AUTH foobar} err catch {r -1 migrate $second_host $second_port list 9 5000 AUTH foobar} err
assert_match {*WRONGPASS*} $err assert_match {*WRONGPASS*} $err
} }
} } {} {external:skip}
} }
...@@ -96,7 +96,9 @@ start_server {tags {"expire"}} { ...@@ -96,7 +96,9 @@ start_server {tags {"expire"}} {
# 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 < 30} {incr j} { for {set j 0} {$j < 30} {incr j} {
r del x y z r del x
r del y
r del z
r psetex x 100 somevalue r psetex x 100 somevalue
after 80 after 80
set a [r get x] set a [r get x]
...@@ -172,32 +174,34 @@ start_server {tags {"expire"}} { ...@@ -172,32 +174,34 @@ start_server {tags {"expire"}} {
r psetex key1 500 a r psetex key1 500 a
r psetex key2 500 a r psetex key2 500 a
r psetex key3 500 a r psetex key3 500 a
set size1 [r dbsize] assert_equal 3 [r dbsize]
# Redis expires random keys ten times every second so we are # Redis expires random keys ten times every second so we are
# fairly sure that all the three keys should be evicted after # fairly sure that all the three keys should be evicted after
# one second. # two seconds.
after 1000 wait_for_condition 20 100 {
set size2 [r dbsize] [r dbsize] eq 0
list $size1 $size2 } fail {
} {3 0} "Keys did not actively expire."
}
}
test {Redis should lazy expire keys} { test {Redis should lazy expire keys} {
r flushdb r flushdb
r debug set-active-expire 0 r debug set-active-expire 0
r psetex key1 500 a r psetex key1{t} 500 a
r psetex key2 500 a r psetex key2{t} 500 a
r psetex key3 500 a r psetex key3{t} 500 a
set size1 [r dbsize] set size1 [r dbsize]
# Redis expires random keys ten times every second so we are # Redis expires random keys ten times every second so we are
# fairly sure that all the three keys should be evicted after # fairly sure that all the three keys should be evicted after
# one second. # one second.
after 1000 after 1000
set size2 [r dbsize] set size2 [r dbsize]
r mget key1 key2 key3 r mget key1{t} key2{t} key3{t}
set size3 [r dbsize] set size3 [r dbsize]
r debug set-active-expire 1 r debug set-active-expire 1
list $size1 $size2 $size3 list $size1 $size2 $size3
} {3 3 0} } {3 3 0} {needs:debug}
test {EXPIRE should not resurrect keys (issue #1026)} { test {EXPIRE should not resurrect keys (issue #1026)} {
r debug set-active-expire 0 r debug set-active-expire 0
...@@ -207,7 +211,7 @@ start_server {tags {"expire"}} { ...@@ -207,7 +211,7 @@ start_server {tags {"expire"}} {
r expire foo 10 r expire foo 10
r debug set-active-expire 1 r debug set-active-expire 1
r exists foo r exists foo
} {0} } {0} {needs:debug}
test {5 keys in, 5 keys out} { test {5 keys in, 5 keys out} {
r flushdb r flushdb
...@@ -279,7 +283,7 @@ start_server {tags {"expire"}} { ...@@ -279,7 +283,7 @@ start_server {tags {"expire"}} {
} {-2} } {-2}
# Start a new server with empty data and AOF file. # Start a new server with empty data and AOF file.
start_server {overrides {appendonly {yes} appendfilename {appendonly.aof} appendfsync always}} { start_server {overrides {appendonly {yes} appendfilename {appendonly.aof} appendfsync always} tags {external:skip}} {
test {All time-to-live(TTL) in commands are propagated as absolute timestamp in milliseconds in AOF} { test {All time-to-live(TTL) in commands are propagated as absolute timestamp in milliseconds in AOF} {
# This test makes sure that expire times are propagated as absolute # This test makes sure that expire times are propagated as absolute
# times to the AOF file and not as relative time, so that when the AOF # times to the AOF file and not as relative time, so that when the AOF
...@@ -417,7 +421,7 @@ start_server {tags {"expire"}} { ...@@ -417,7 +421,7 @@ start_server {tags {"expire"}} {
assert_equal [r pexpiretime foo16] "-1" ; # foo16 has no TTL assert_equal [r pexpiretime foo16] "-1" ; # foo16 has no TTL
assert_equal [r pexpiretime foo17] $ttl17 assert_equal [r pexpiretime foo17] $ttl17
assert_equal [r pexpiretime foo18] $ttl18 assert_equal [r pexpiretime foo18] $ttl18
} } {} {needs:debug}
} }
test {All TTL in commands are propagated as absolute timestamp in replication stream} { test {All TTL in commands are propagated as absolute timestamp in replication stream} {
...@@ -484,7 +488,7 @@ start_server {tags {"expire"}} { ...@@ -484,7 +488,7 @@ start_server {tags {"expire"}} {
} }
# Start another server to test replication of TTLs # Start another server to test replication of TTLs
start_server {} { start_server {tags {needs:repl external:skip}} {
# Set the outer layer server as primary # Set the outer layer server as primary
set primary [srv -1 client] set primary [srv -1 client]
set primary_host [srv -1 host] set primary_host [srv -1 host]
...@@ -566,7 +570,7 @@ start_server {tags {"expire"}} { ...@@ -566,7 +570,7 @@ start_server {tags {"expire"}} {
r debug loadaof r debug loadaof
set ttl [r ttl foo] set ttl [r ttl foo]
assert {$ttl <= 98 && $ttl > 90} assert {$ttl <= 98 && $ttl > 90}
} } {} {needs:debug}
test {GETEX use of PERSIST option should remove TTL} { test {GETEX use of PERSIST option should remove TTL} {
r set foo bar EX 100 r set foo bar EX 100
...@@ -580,7 +584,7 @@ start_server {tags {"expire"}} { ...@@ -580,7 +584,7 @@ start_server {tags {"expire"}} {
after 2000 after 2000
r debug loadaof r debug loadaof
r ttl foo r ttl foo
} {-1} } {-1} {needs:debug}
test {GETEX propagate as to replica as PERSIST, DEL, or nothing} { test {GETEX propagate as to replica as PERSIST, DEL, or nothing} {
set repl [attach_to_replication_stream] set repl [attach_to_replication_stream]
...@@ -594,5 +598,5 @@ start_server {tags {"expire"}} { ...@@ -594,5 +598,5 @@ start_server {tags {"expire"}} {
{persist foo} {persist foo}
{del foo} {del foo}
} }
} } {} {needs:repl}
} }
...@@ -325,74 +325,74 @@ start_server {tags {"geo"}} { ...@@ -325,74 +325,74 @@ start_server {tags {"geo"}} {
} }
test {GEORADIUS STORE option: syntax error} { test {GEORADIUS STORE option: syntax error} {
r del points r del points{t}
r geoadd points 13.361389 38.115556 "Palermo" \ r geoadd points{t} 13.361389 38.115556 "Palermo" \
15.087269 37.502669 "Catania" 15.087269 37.502669 "Catania"
catch {r georadius points 13.361389 38.115556 50 km store} e catch {r georadius points{t} 13.361389 38.115556 50 km store} e
set e set e
} {*ERR*syntax*} } {*ERR*syntax*}
test {GEOSEARCHSTORE STORE option: syntax error} { test {GEOSEARCHSTORE STORE option: syntax error} {
catch {r geosearchstore abc points fromlonlat 13.361389 38.115556 byradius 50 km store abc} e catch {r geosearchstore abc{t} points{t} fromlonlat 13.361389 38.115556 byradius 50 km store abc{t}} e
set e set e
} {*ERR*syntax*} } {*ERR*syntax*}
test {GEORANGE STORE option: incompatible options} { test {GEORANGE STORE option: incompatible options} {
r del points r del points{t}
r geoadd points 13.361389 38.115556 "Palermo" \ r geoadd points{t} 13.361389 38.115556 "Palermo" \
15.087269 37.502669 "Catania" 15.087269 37.502669 "Catania"
catch {r georadius points 13.361389 38.115556 50 km store points2 withdist} e catch {r georadius points{t} 13.361389 38.115556 50 km store points2{t} withdist} e
assert_match {*ERR*} $e assert_match {*ERR*} $e
catch {r georadius points 13.361389 38.115556 50 km store points2 withhash} e catch {r georadius points{t} 13.361389 38.115556 50 km store points2{t} withhash} e
assert_match {*ERR*} $e assert_match {*ERR*} $e
catch {r georadius points 13.361389 38.115556 50 km store points2 withcoords} e catch {r georadius points{t} 13.361389 38.115556 50 km store points2{t} withcoords} e
assert_match {*ERR*} $e assert_match {*ERR*} $e
} }
test {GEORANGE STORE option: plain usage} { test {GEORANGE STORE option: plain usage} {
r del points r del points{t}
r geoadd points 13.361389 38.115556 "Palermo" \ r geoadd points{t} 13.361389 38.115556 "Palermo" \
15.087269 37.502669 "Catania" 15.087269 37.502669 "Catania"
r georadius points 13.361389 38.115556 500 km store points2 r georadius points{t} 13.361389 38.115556 500 km store points2{t}
assert_equal [r zrange points 0 -1] [r zrange points2 0 -1] assert_equal [r zrange points{t} 0 -1] [r zrange points2{t} 0 -1]
} }
test {GEOSEARCHSTORE STORE option: plain usage} { test {GEOSEARCHSTORE STORE option: plain usage} {
r geosearchstore points2 points fromlonlat 13.361389 38.115556 byradius 500 km r geosearchstore points2{t} points{t} fromlonlat 13.361389 38.115556 byradius 500 km
assert_equal [r zrange points 0 -1] [r zrange points2 0 -1] assert_equal [r zrange points{t} 0 -1] [r zrange points2{t} 0 -1]
} }
test {GEORANGE STOREDIST option: plain usage} { test {GEORANGE STOREDIST option: plain usage} {
r del points r del points{t}
r geoadd points 13.361389 38.115556 "Palermo" \ r geoadd points{t} 13.361389 38.115556 "Palermo" \
15.087269 37.502669 "Catania" 15.087269 37.502669 "Catania"
r georadius points 13.361389 38.115556 500 km storedist points2 r georadius points{t} 13.361389 38.115556 500 km storedist points2{t}
set res [r zrange points2 0 -1 withscores] set res [r zrange points2{t} 0 -1 withscores]
assert {[lindex $res 1] < 1} assert {[lindex $res 1] < 1}
assert {[lindex $res 3] > 166} assert {[lindex $res 3] > 166}
assert {[lindex $res 3] < 167} assert {[lindex $res 3] < 167}
} }
test {GEOSEARCHSTORE STOREDIST option: plain usage} { test {GEOSEARCHSTORE STOREDIST option: plain usage} {
r geosearchstore points2 points fromlonlat 13.361389 38.115556 byradius 500 km storedist r geosearchstore points2{t} points{t} fromlonlat 13.361389 38.115556 byradius 500 km storedist
set res [r zrange points2 0 -1 withscores] set res [r zrange points2{t} 0 -1 withscores]
assert {[lindex $res 1] < 1} assert {[lindex $res 1] < 1}
assert {[lindex $res 3] > 166} assert {[lindex $res 3] > 166}
assert {[lindex $res 3] < 167} assert {[lindex $res 3] < 167}
} }
test {GEORANGE STOREDIST option: COUNT ASC and DESC} { test {GEORANGE STOREDIST option: COUNT ASC and DESC} {
r del points r del points{t}
r geoadd points 13.361389 38.115556 "Palermo" \ r geoadd points{t} 13.361389 38.115556 "Palermo" \
15.087269 37.502669 "Catania" 15.087269 37.502669 "Catania"
r georadius points 13.361389 38.115556 500 km storedist points2 asc count 1 r georadius points{t} 13.361389 38.115556 500 km storedist points2{t} asc count 1
assert {[r zcard points2] == 1} assert {[r zcard points2{t}] == 1}
set res [r zrange points2 0 -1 withscores] set res [r zrange points2{t} 0 -1 withscores]
assert {[lindex $res 0] eq "Palermo"} assert {[lindex $res 0] eq "Palermo"}
r georadius points 13.361389 38.115556 500 km storedist points2 desc count 1 r georadius points{t} 13.361389 38.115556 500 km storedist points2{t} desc count 1
assert {[r zcard points2] == 1} assert {[r zcard points2{t}] == 1}
set res [r zrange points2 0 -1 withscores] set res [r zrange points2{t} 0 -1 withscores]
assert {[lindex $res 0] eq "Catania"} assert {[lindex $res 0] eq "Catania"}
} }
......
...@@ -2,7 +2,7 @@ start_server {tags {"hll"}} { ...@@ -2,7 +2,7 @@ start_server {tags {"hll"}} {
test {HyperLogLog self test passes} { test {HyperLogLog self test passes} {
catch {r pfselftest} e catch {r pfselftest} e
set e set e
} {OK} } {OK} {needs:pfdebug}
test {PFADD without arguments creates an HLL value} { test {PFADD without arguments creates an HLL value} {
r pfadd hll r pfadd hll
...@@ -57,11 +57,12 @@ start_server {tags {"hll"}} { ...@@ -57,11 +57,12 @@ start_server {tags {"hll"}} {
assert {[r pfdebug encoding hll] eq {dense}} assert {[r pfdebug encoding hll] eq {dense}}
} }
} }
} } {} {needs:pfdebug}
test {HyperLogLog sparse encoding stress test} { test {HyperLogLog sparse encoding stress test} {
for {set x 0} {$x < 1000} {incr x} { for {set x 0} {$x < 1000} {incr x} {
r del hll1 hll2 r del hll1
r del hll2
set numele [randomInt 100] set numele [randomInt 100]
set elements {} set elements {}
for {set j 0} {$j < $numele} {incr j} { for {set j 0} {$j < $numele} {incr j} {
...@@ -77,7 +78,7 @@ start_server {tags {"hll"}} { ...@@ -77,7 +78,7 @@ start_server {tags {"hll"}} {
# Cardinality estimated should match exactly. # Cardinality estimated should match exactly.
assert {[r pfcount hll1] eq [r pfcount hll2]} assert {[r pfcount hll1] eq [r pfcount hll2]}
} }
} } {} {needs:pfdebug}
test {Corrupted sparse HyperLogLogs are detected: Additional at tail} { test {Corrupted sparse HyperLogLogs are detected: Additional at tail} {
r del hll r del hll
...@@ -144,34 +145,34 @@ start_server {tags {"hll"}} { ...@@ -144,34 +145,34 @@ start_server {tags {"hll"}} {
} }
test {PFADD, PFCOUNT, PFMERGE type checking works} { test {PFADD, PFCOUNT, PFMERGE type checking works} {
r set foo bar r set foo{t} bar
catch {r pfadd foo 1} e catch {r pfadd foo{t} 1} e
assert_match {*WRONGTYPE*} $e assert_match {*WRONGTYPE*} $e
catch {r pfcount foo} e catch {r pfcount foo{t}} e
assert_match {*WRONGTYPE*} $e assert_match {*WRONGTYPE*} $e
catch {r pfmerge bar foo} e catch {r pfmerge bar{t} foo{t}} e
assert_match {*WRONGTYPE*} $e assert_match {*WRONGTYPE*} $e
catch {r pfmerge foo bar} e catch {r pfmerge foo{t} bar{t}} e
assert_match {*WRONGTYPE*} $e assert_match {*WRONGTYPE*} $e
} }
test {PFMERGE results on the cardinality of union of sets} { test {PFMERGE results on the cardinality of union of sets} {
r del hll hll1 hll2 hll3 r del hll{t} hll1{t} hll2{t} hll3{t}
r pfadd hll1 a b c r pfadd hll1{t} a b c
r pfadd hll2 b c d r pfadd hll2{t} b c d
r pfadd hll3 c d e r pfadd hll3{t} c d e
r pfmerge hll hll1 hll2 hll3 r pfmerge hll{t} hll1{t} hll2{t} hll3{t}
r pfcount hll r pfcount hll{t}
} {5} } {5}
test {PFCOUNT multiple-keys merge returns cardinality of union #1} { test {PFCOUNT multiple-keys merge returns cardinality of union #1} {
r del hll1 hll2 hll3 r del hll1{t} hll2{t} hll3{t}
for {set x 1} {$x < 10000} {incr x} { for {set x 1} {$x < 10000} {incr x} {
r pfadd hll1 "foo-$x" r pfadd hll1{t} "foo-$x"
r pfadd hll2 "bar-$x" r pfadd hll2{t} "bar-$x"
r pfadd hll3 "zap-$x" r pfadd hll3{t} "zap-$x"
set card [r pfcount hll1 hll2 hll3] set card [r pfcount hll1{t} hll2{t} hll3{t}]
set realcard [expr {$x*3}] set realcard [expr {$x*3}]
set err [expr {abs($card-$realcard)}] set err [expr {abs($card-$realcard)}]
assert {$err < (double($card)/100)*5} assert {$err < (double($card)/100)*5}
...@@ -179,17 +180,17 @@ start_server {tags {"hll"}} { ...@@ -179,17 +180,17 @@ start_server {tags {"hll"}} {
} }
test {PFCOUNT multiple-keys merge returns cardinality of union #2} { test {PFCOUNT multiple-keys merge returns cardinality of union #2} {
r del hll1 hll2 hll3 r del hll1{t} hll2{t} hll3{t}
set elements {} set elements {}
for {set x 1} {$x < 10000} {incr x} { for {set x 1} {$x < 10000} {incr x} {
for {set j 1} {$j <= 3} {incr j} { for {set j 1} {$j <= 3} {incr j} {
set rint [randomInt 20000] set rint [randomInt 20000]
r pfadd hll$j $rint r pfadd hll$j{t} $rint
lappend elements $rint lappend elements $rint
} }
} }
set realcard [llength [lsort -unique $elements]] set realcard [llength [lsort -unique $elements]]
set card [r pfcount hll1 hll2 hll3] set card [r pfcount hll1{t} hll2{t} hll3{t}]
set err [expr {abs($card-$realcard)}] set err [expr {abs($card-$realcard)}]
assert {$err < (double($card)/100)*5} assert {$err < (double($card)/100)*5}
} }
...@@ -198,7 +199,7 @@ start_server {tags {"hll"}} { ...@@ -198,7 +199,7 @@ start_server {tags {"hll"}} {
r del hll r del hll
r pfadd hll 1 2 3 r pfadd hll 1 2 3
llength [r pfdebug getreg hll] llength [r pfdebug getreg hll]
} {16384} } {16384} {needs:pfdebug}
test {PFADD / PFCOUNT cache invalidation works} { test {PFADD / PFCOUNT cache invalidation works} {
r del hll r del hll
......
...@@ -6,7 +6,7 @@ proc errorstat {cmd} { ...@@ -6,7 +6,7 @@ proc errorstat {cmd} {
return [errorrstat $cmd r] return [errorrstat $cmd r]
} }
start_server {tags {"info"}} { start_server {tags {"info" "external:skip"}} {
start_server {} { start_server {} {
test {errorstats: failed call authentication error} { test {errorstats: failed call authentication error} {
......
...@@ -21,9 +21,9 @@ start_server {tags {"introspection"}} { ...@@ -21,9 +21,9 @@ start_server {tags {"introspection"}} {
test {TOUCH returns the number of existing keys specified} { test {TOUCH returns the number of existing keys specified} {
r flushdb r flushdb
r set key1 1 r set key1{t} 1
r set key2 2 r set key2{t} 2
r touch key0 key1 key2 key3 r touch key0{t} key1{t} key2{t} key3{t}
} 2 } 2
test {command stats for GEOADD} { test {command stats for GEOADD} {
...@@ -31,7 +31,7 @@ start_server {tags {"introspection"}} { ...@@ -31,7 +31,7 @@ start_server {tags {"introspection"}} {
r GEOADD foo 0 0 bar r GEOADD foo 0 0 bar
assert_match {*calls=1,*} [cmdstat geoadd] assert_match {*calls=1,*} [cmdstat geoadd]
assert_match {} [cmdstat zadd] assert_match {} [cmdstat zadd]
} } {} {needs:config-resetstat}
test {command stats for EXPIRE} { test {command stats for EXPIRE} {
r config resetstat r config resetstat
...@@ -39,7 +39,7 @@ start_server {tags {"introspection"}} { ...@@ -39,7 +39,7 @@ start_server {tags {"introspection"}} {
r EXPIRE foo 0 r EXPIRE foo 0
assert_match {*calls=1,*} [cmdstat expire] assert_match {*calls=1,*} [cmdstat expire]
assert_match {} [cmdstat del] assert_match {} [cmdstat del]
} } {} {needs:config-resetstat}
test {command stats for BRPOP} { test {command stats for BRPOP} {
r config resetstat r config resetstat
...@@ -47,21 +47,21 @@ start_server {tags {"introspection"}} { ...@@ -47,21 +47,21 @@ start_server {tags {"introspection"}} {
r BRPOP list 0 r BRPOP list 0
assert_match {*calls=1,*} [cmdstat brpop] assert_match {*calls=1,*} [cmdstat brpop]
assert_match {} [cmdstat rpop] assert_match {} [cmdstat rpop]
} } {} {needs:config-resetstat}
test {command stats for MULTI} { test {command stats for MULTI} {
r config resetstat r config resetstat
r MULTI r MULTI
r set foo bar r set foo{t} bar
r GEOADD foo2 0 0 bar r GEOADD foo2{t} 0 0 bar
r EXPIRE foo2 0 r EXPIRE foo2{t} 0
r EXEC r EXEC
assert_match {*calls=1,*} [cmdstat multi] assert_match {*calls=1,*} [cmdstat multi]
assert_match {*calls=1,*} [cmdstat exec] assert_match {*calls=1,*} [cmdstat exec]
assert_match {*calls=1,*} [cmdstat set] assert_match {*calls=1,*} [cmdstat set]
assert_match {*calls=1,*} [cmdstat expire] assert_match {*calls=1,*} [cmdstat expire]
assert_match {*calls=1,*} [cmdstat geoadd] assert_match {*calls=1,*} [cmdstat geoadd]
} } {} {needs:config-resetstat}
test {command stats for scripts} { test {command stats for scripts} {
r config resetstat r config resetstat
...@@ -75,5 +75,5 @@ start_server {tags {"introspection"}} { ...@@ -75,5 +75,5 @@ start_server {tags {"introspection"}} {
assert_match {*calls=2,*} [cmdstat set] assert_match {*calls=2,*} [cmdstat set]
assert_match {*calls=1,*} [cmdstat expire] assert_match {*calls=1,*} [cmdstat expire]
assert_match {*calls=1,*} [cmdstat geoadd] assert_match {*calls=1,*} [cmdstat geoadd]
} } {} {needs:config-resetstat}
} }
start_server {tags {"introspection"}} { start_server {tags {"introspection"}} {
test {CLIENT LIST} { test {CLIENT LIST} {
r client list r client list
} {*addr=*:* fd=* age=* idle=* flags=N db=9 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=* argv-mem=* obl=0 oll=0 omem=0 tot-mem=* events=r cmd=client*} } {*addr=*:* fd=* age=* idle=* flags=N db=* sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=* argv-mem=* obl=0 oll=0 omem=0 tot-mem=* events=r cmd=client*}
test {CLIENT LIST with IDs} { test {CLIENT LIST with IDs} {
set myid [r client id] set myid [r client id]
...@@ -11,7 +11,7 @@ start_server {tags {"introspection"}} { ...@@ -11,7 +11,7 @@ start_server {tags {"introspection"}} {
test {CLIENT INFO} { test {CLIENT INFO} {
r client info r client info
} {*addr=*:* fd=* age=* idle=* flags=N db=9 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=* argv-mem=* obl=0 oll=0 omem=0 tot-mem=* events=r cmd=client*} } {*addr=*:* fd=* age=* idle=* flags=N db=* sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=* argv-mem=* obl=0 oll=0 omem=0 tot-mem=* events=r cmd=client*}
test {MONITOR can log executed commands} { test {MONITOR can log executed commands} {
set rd [redis_deferring_client] set rd [redis_deferring_client]
...@@ -50,7 +50,7 @@ start_server {tags {"introspection"}} { ...@@ -50,7 +50,7 @@ start_server {tags {"introspection"}} {
assert_match {*"auth"*"(redacted)"*"(redacted)"*} [$rd read] assert_match {*"auth"*"(redacted)"*"(redacted)"*} [$rd read]
assert_match {*"hello"*"2"*"AUTH"*"(redacted)"*"(redacted)"*} [$rd read] assert_match {*"hello"*"2"*"AUTH"*"(redacted)"*"(redacted)"*} [$rd read]
$rd close $rd close
} } {0} {needs:repl}
test {MONITOR correctly handles multi-exec cases} { test {MONITOR correctly handles multi-exec cases} {
set rd [redis_deferring_client] set rd [redis_deferring_client]
...@@ -125,7 +125,7 @@ start_server {tags {"introspection"}} { ...@@ -125,7 +125,7 @@ start_server {tags {"introspection"}} {
# Defaults # Defaults
assert_match [r config get save] {save {100 100}} assert_match [r config get save] {save {100 100}}
} }
} } {} {external:skip}
test {CONFIG sanity} { test {CONFIG sanity} {
# Do CONFIG GET, CONFIG SET and then CONFIG GET again # Do CONFIG GET, CONFIG SET and then CONFIG GET again
...@@ -178,6 +178,11 @@ start_server {tags {"introspection"}} { ...@@ -178,6 +178,11 @@ start_server {tags {"introspection"}} {
} }
} }
# TODO: Remove this when CONFIG SET bind "" is fixed.
if {$::external} {
append skip_configs bind
}
set configs {} set configs {}
foreach {k v} [r config get *] { foreach {k v} [r config get *] {
if {[lsearch $skip_configs $k] != -1} { if {[lsearch $skip_configs $k] != -1} {
...@@ -224,7 +229,7 @@ start_server {tags {"introspection"}} { ...@@ -224,7 +229,7 @@ start_server {tags {"introspection"}} {
dict for {k v} $configs { dict for {k v} $configs {
assert_equal $v [lindex [r config get $k] 1] assert_equal $v [lindex [r config get $k] 1]
} }
} } {} {external:skip}
test {CONFIG REWRITE handles save properly} { test {CONFIG REWRITE handles save properly} {
r config set save "3600 1 300 100 60 10000" r config set save "3600 1 300 100 60 10000"
...@@ -244,7 +249,7 @@ start_server {tags {"introspection"}} { ...@@ -244,7 +249,7 @@ start_server {tags {"introspection"}} {
restart_server 0 true false restart_server 0 true false
assert_equal [r config get save] {save {}} assert_equal [r config get save] {save {}}
} }
} } {} {external:skip}
# 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.
......
...@@ -7,12 +7,18 @@ start_server {tags {"keyspace"}} { ...@@ -7,12 +7,18 @@ start_server {tags {"keyspace"}} {
} {} } {}
test {Vararg DEL} { test {Vararg DEL} {
r set foo1 a r set foo1{t} a
r set foo2 b r set foo2{t} b
r set foo3 c r set foo3{t} c
list [r del foo1 foo2 foo3 foo4] [r mget foo1 foo2 foo3] list [r del foo1{t} foo2{t} foo3{t} foo4{t}] [r mget foo1{t} foo2{t} foo3{t}]
} {3 {{} {} {}}} } {3 {{} {} {}}}
test {Untagged multi-key commands} {
r mset foo1 a foo2 b foo3 c
assert_equal {a b c {}} [r mget foo1 foo2 foo3 foo4]
r del foo1 foo2 foo3 foo4
} {3} {cluster:skip}
test {KEYS with pattern} { test {KEYS with pattern} {
foreach key {key_x key_y key_z foo_a foo_b foo_c} { foreach key {key_x key_y key_z foo_a foo_b foo_c} {
r set $key hello r set $key hello
...@@ -39,7 +45,7 @@ start_server {tags {"keyspace"}} { ...@@ -39,7 +45,7 @@ start_server {tags {"keyspace"}} {
after 1100 after 1100
assert_equal 0 [r del keyExpire] assert_equal 0 [r del keyExpire]
r debug set-active-expire 1 r debug set-active-expire 1
} } {OK} {needs:debug}
test {EXISTS} { test {EXISTS} {
set res {} set res {}
...@@ -74,10 +80,10 @@ start_server {tags {"keyspace"}} { ...@@ -74,10 +80,10 @@ start_server {tags {"keyspace"}} {
} {1} } {1}
test {RENAME basic usage} { test {RENAME basic usage} {
r set mykey hello r set mykey{t} hello
r rename mykey mykey1 r rename mykey{t} mykey1{t}
r rename mykey1 mykey2 r rename mykey1{t} mykey2{t}
r get mykey2 r get mykey2{t}
} {hello} } {hello}
test {RENAME source key should no longer exist} { test {RENAME source key should no longer exist} {
...@@ -85,35 +91,35 @@ start_server {tags {"keyspace"}} { ...@@ -85,35 +91,35 @@ start_server {tags {"keyspace"}} {
} {0} } {0}
test {RENAME against already existing key} { test {RENAME against already existing key} {
r set mykey a r set mykey{t} a
r set mykey2 b r set mykey2{t} b
r rename mykey2 mykey r rename mykey2{t} mykey{t}
set res [r get mykey] set res [r get mykey{t}]
append res [r exists mykey2] append res [r exists mykey2{t}]
} {b0} } {b0}
test {RENAMENX basic usage} { test {RENAMENX basic usage} {
r del mykey r del mykey{t}
r del mykey2 r del mykey2{t}
r set mykey foobar r set mykey{t} foobar
r renamenx mykey mykey2 r renamenx mykey{t} mykey2{t}
set res [r get mykey2] set res [r get mykey2{t}]
append res [r exists mykey] append res [r exists mykey{t}]
} {foobar0} } {foobar0}
test {RENAMENX against already existing key} { test {RENAMENX against already existing key} {
r set mykey foo r set mykey{t} foo
r set mykey2 bar r set mykey2{t} bar
r renamenx mykey mykey2 r renamenx mykey{t} mykey2{t}
} {0} } {0}
test {RENAMENX against already existing key (2)} { test {RENAMENX against already existing key (2)} {
set res [r get mykey] set res [r get mykey{t}]
append res [r get mykey2] append res [r get mykey2{t}]
} {foobar} } {foobar}
test {RENAME against non existing source key} { test {RENAME against non existing source key} {
catch {r rename nokey foobar} err catch {r rename nokey{t} foobar{t}} err
format $err format $err
} {ERR*} } {ERR*}
...@@ -134,22 +140,22 @@ start_server {tags {"keyspace"}} { ...@@ -134,22 +140,22 @@ start_server {tags {"keyspace"}} {
} {ERR*} } {ERR*}
test {RENAME with volatile key, should move the TTL as well} { test {RENAME with volatile key, should move the TTL as well} {
r del mykey mykey2 r del mykey{t} mykey2{t}
r set mykey foo r set mykey{t} foo
r expire mykey 100 r expire mykey{t} 100
assert {[r ttl mykey] > 95 && [r ttl mykey] <= 100} assert {[r ttl mykey{t}] > 95 && [r ttl mykey{t}] <= 100}
r rename mykey mykey2 r rename mykey{t} mykey2{t}
assert {[r ttl mykey2] > 95 && [r ttl mykey2] <= 100} assert {[r ttl mykey2{t}] > 95 && [r ttl mykey2{t}] <= 100}
} }
test {RENAME with volatile key, should not inherit TTL of target key} { test {RENAME with volatile key, should not inherit TTL of target key} {
r del mykey mykey2 r del mykey{t} mykey2{t}
r set mykey foo r set mykey{t} foo
r set mykey2 bar r set mykey2{t} bar
r expire mykey2 100 r expire mykey2{t} 100
assert {[r ttl mykey] == -1 && [r ttl mykey2] > 0} assert {[r ttl mykey{t}] == -1 && [r ttl mykey2{t}] > 0}
r rename mykey mykey2 r rename mykey{t} mykey2{t}
r ttl mykey2 r ttl mykey2{t}
} {-1} } {-1}
test {DEL all keys again (DB 0)} { test {DEL all keys again (DB 0)} {
...@@ -167,212 +173,216 @@ start_server {tags {"keyspace"}} { ...@@ -167,212 +173,216 @@ start_server {tags {"keyspace"}} {
set res [r dbsize] set res [r dbsize]
r select 9 r select 9
format $res format $res
} {0} } {0} {singledb:skip}
test {COPY basic usage for string} { test {COPY basic usage for string} {
r set mykey foobar r set mykey{t} foobar
set res {} set res {}
r copy mykey mynewkey r copy mykey{t} mynewkey{t}
lappend res [r get mynewkey] lappend res [r get mynewkey{t}]
lappend res [r dbsize] lappend res [r dbsize]
r copy mykey mynewkey DB 10 if {$::singledb} {
assert_equal [list foobar 2] [format $res]
} else {
r copy mykey{t} mynewkey{t} DB 10
r select 10 r select 10
lappend res [r get mynewkey] lappend res [r get mynewkey{t}]
lappend res [r dbsize] lappend res [r dbsize]
r select 9 r select 9
format $res assert_equal [list foobar 2 foobar 1] [format $res]
} [list foobar 2 foobar 1] }
}
test {COPY for string does not replace an existing key without REPLACE option} { test {COPY for string does not replace an existing key without REPLACE option} {
r set mykey2 hello r set mykey2{t} hello
catch {r copy mykey2 mynewkey DB 10} e catch {r copy mykey2{t} mynewkey{t} DB 10} e
set e set e
} {0} } {0} {singledb:skip}
test {COPY for string can replace an existing key with REPLACE option} { test {COPY for string can replace an existing key with REPLACE option} {
r copy mykey2 mynewkey DB 10 REPLACE r copy mykey2{t} mynewkey{t} DB 10 REPLACE
r select 10 r select 10
r get mynewkey r get mynewkey{t}
} {hello} } {hello} {singledb:skip}
test {COPY for string ensures that copied data is independent of copying data} { test {COPY for string ensures that copied data is independent of copying data} {
r flushdb r flushdb
r select 9 r select 9
r set mykey foobar r set mykey{t} foobar
set res {} set res {}
r copy mykey mynewkey DB 10 r copy mykey{t} mynewkey{t} DB 10
r select 10 r select 10
lappend res [r get mynewkey] lappend res [r get mynewkey{t}]
r set mynewkey hoge r set mynewkey{t} hoge
lappend res [r get mynewkey] lappend res [r get mynewkey{t}]
r select 9 r select 9
lappend res [r get mykey] lappend res [r get mykey{t}]
r select 10 r select 10
r flushdb r flushdb
r select 9 r select 9
format $res format $res
} [list foobar hoge foobar] } [list foobar hoge foobar] {singledb:skip}
test {COPY for string does not copy data to no-integer DB} { test {COPY for string does not copy data to no-integer DB} {
r set mykey foobar r set mykey{t} foobar
catch {r copy mykey mynewkey DB notanumber} e catch {r copy mykey{t} mynewkey{t} DB notanumber} e
set e set e
} {ERR value is not an integer or out of range} } {ERR value is not an integer or out of range}
test {COPY can copy key expire metadata as well} { test {COPY can copy key expire metadata as well} {
r set mykey foobar ex 100 r set mykey{t} foobar ex 100
r copy mykey mynewkey REPLACE r copy mykey{t} mynewkey{t} REPLACE
assert {[r ttl mynewkey] > 0 && [r ttl mynewkey] <= 100} assert {[r ttl mynewkey{t}] > 0 && [r ttl mynewkey{t}] <= 100}
assert {[r get mynewkey] eq "foobar"} assert {[r get mynewkey{t}] eq "foobar"}
} }
test {COPY does not create an expire if it does not exist} { test {COPY does not create an expire if it does not exist} {
r set mykey foobar r set mykey{t} foobar
assert {[r ttl mykey] == -1} assert {[r ttl mykey{t}] == -1}
r copy mykey mynewkey REPLACE r copy mykey{t} mynewkey{t} REPLACE
assert {[r ttl mynewkey] == -1} assert {[r ttl mynewkey{t}] == -1}
assert {[r get mynewkey] eq "foobar"} assert {[r get mynewkey{t}] eq "foobar"}
} }
test {COPY basic usage for list} { test {COPY basic usage for list} {
r del mylist mynewlist r del mylist{t} mynewlist{t}
r lpush mylist a b c d r lpush mylist{t} a b c d
r copy mylist mynewlist r copy mylist{t} mynewlist{t}
set digest [r debug digest-value mylist] set digest [debug_digest_value mylist{t}]
assert_equal $digest [r debug digest-value mynewlist] assert_equal $digest [debug_digest_value mynewlist{t}]
assert_equal 1 [r object refcount mylist] assert_equal 1 [r object refcount mylist{t}]
assert_equal 1 [r object refcount mynewlist] assert_equal 1 [r object refcount mynewlist{t}]
r del mylist r del mylist{t}
assert_equal $digest [r debug digest-value mynewlist] assert_equal $digest [debug_digest_value mynewlist{t}]
} }
test {COPY basic usage for intset set} { test {COPY basic usage for intset set} {
r del set1 newset1 r del set1{t} newset1{t}
r sadd set1 1 2 3 r sadd set1{t} 1 2 3
assert_encoding intset set1 assert_encoding intset set1{t}
r copy set1 newset1 r copy set1{t} newset1{t}
set digest [r debug digest-value set1] set digest [debug_digest_value set1{t}]
assert_equal $digest [r debug digest-value newset1] assert_equal $digest [debug_digest_value newset1{t}]
assert_equal 1 [r object refcount set1] assert_equal 1 [r object refcount set1{t}]
assert_equal 1 [r object refcount newset1] assert_equal 1 [r object refcount newset1{t}]
r del set1 r del set1{t}
assert_equal $digest [r debug digest-value newset1] assert_equal $digest [debug_digest_value newset1{t}]
} }
test {COPY basic usage for hashtable set} { test {COPY basic usage for hashtable set} {
r del set2 newset2 r del set2{t} newset2{t}
r sadd set2 1 2 3 a r sadd set2{t} 1 2 3 a
assert_encoding hashtable set2 assert_encoding hashtable set2{t}
r copy set2 newset2 r copy set2{t} newset2{t}
set digest [r debug digest-value set2] set digest [debug_digest_value set2{t}]
assert_equal $digest [r debug digest-value newset2] assert_equal $digest [debug_digest_value newset2{t}]
assert_equal 1 [r object refcount set2] assert_equal 1 [r object refcount set2{t}]
assert_equal 1 [r object refcount newset2] assert_equal 1 [r object refcount newset2{t}]
r del set2 r del set2{t}
assert_equal $digest [r debug digest-value newset2] assert_equal $digest [debug_digest_value newset2{t}]
} }
test {COPY basic usage for ziplist sorted set} { test {COPY basic usage for ziplist sorted set} {
r del zset1 newzset1 r del zset1{t} newzset1{t}
r zadd zset1 123 foobar r zadd zset1{t} 123 foobar
assert_encoding ziplist zset1 assert_encoding ziplist zset1{t}
r copy zset1 newzset1 r copy zset1{t} newzset1{t}
set digest [r debug digest-value zset1] set digest [debug_digest_value zset1{t}]
assert_equal $digest [r debug digest-value newzset1] assert_equal $digest [debug_digest_value newzset1{t}]
assert_equal 1 [r object refcount zset1] assert_equal 1 [r object refcount zset1{t}]
assert_equal 1 [r object refcount newzset1] assert_equal 1 [r object refcount newzset1{t}]
r del zset1 r del zset1{t}
assert_equal $digest [r debug digest-value newzset1] assert_equal $digest [debug_digest_value newzset1{t}]
} }
test {COPY basic usage for skiplist sorted set} { test {COPY basic usage for skiplist sorted set} {
r del zset2 newzset2 r del zset2{t} newzset2{t}
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
for {set j 0} {$j < 130} {incr j} { for {set j 0} {$j < 130} {incr j} {
r zadd zset2 [randomInt 50] ele-[randomInt 10] r zadd zset2{t} [randomInt 50] ele-[randomInt 10]
} }
assert_encoding skiplist zset2 assert_encoding skiplist zset2{t}
r copy zset2 newzset2 r copy zset2{t} newzset2{t}
set digest [r debug digest-value zset2] set digest [debug_digest_value zset2{t}]
assert_equal $digest [r debug digest-value newzset2] assert_equal $digest [debug_digest_value newzset2{t}]
assert_equal 1 [r object refcount zset2] assert_equal 1 [r object refcount zset2{t}]
assert_equal 1 [r object refcount newzset2] assert_equal 1 [r object refcount newzset2{t}]
r del zset2 r del zset2{t}
assert_equal $digest [r debug digest-value newzset2] assert_equal $digest [debug_digest_value newzset2{t}]
r config set zset-max-ziplist-entries $original_max r config set zset-max-ziplist-entries $original_max
} }
test {COPY basic usage for ziplist hash} { test {COPY basic usage for ziplist hash} {
r del hash1 newhash1 r del hash1{t} newhash1{t}
r hset hash1 tmp 17179869184 r hset hash1{t} tmp 17179869184
assert_encoding ziplist hash1 assert_encoding ziplist hash1{t}
r copy hash1 newhash1 r copy hash1{t} newhash1{t}
set digest [r debug digest-value hash1] set digest [debug_digest_value hash1{t}]
assert_equal $digest [r debug digest-value newhash1] assert_equal $digest [debug_digest_value newhash1{t}]
assert_equal 1 [r object refcount hash1] assert_equal 1 [r object refcount hash1{t}]
assert_equal 1 [r object refcount newhash1] assert_equal 1 [r object refcount newhash1{t}]
r del hash1 r del hash1{t}
assert_equal $digest [r debug digest-value newhash1] assert_equal $digest [debug_digest_value newhash1{t}]
} }
test {COPY basic usage for hashtable hash} { test {COPY basic usage for hashtable hash} {
r del hash2 newhash2 r del hash2{t} newhash2{t}
set original_max [lindex [r config get hash-max-ziplist-entries] 1] set original_max [lindex [r config get hash-max-ziplist-entries] 1]
r config set hash-max-ziplist-entries 0 r config set hash-max-ziplist-entries 0
for {set i 0} {$i < 64} {incr i} { for {set i 0} {$i < 64} {incr i} {
r hset hash2 [randomValue] [randomValue] r hset hash2{t} [randomValue] [randomValue]
} }
assert_encoding hashtable hash2 assert_encoding hashtable hash2{t}
r copy hash2 newhash2 r copy hash2{t} newhash2{t}
set digest [r debug digest-value hash2] set digest [debug_digest_value hash2{t}]
assert_equal $digest [r debug digest-value newhash2] assert_equal $digest [debug_digest_value newhash2{t}]
assert_equal 1 [r object refcount hash2] assert_equal 1 [r object refcount hash2{t}]
assert_equal 1 [r object refcount newhash2] assert_equal 1 [r object refcount newhash2{t}]
r del hash2 r del hash2{t}
assert_equal $digest [r debug digest-value newhash2] assert_equal $digest [debug_digest_value newhash2{t}]
r config set hash-max-ziplist-entries $original_max r config set hash-max-ziplist-entries $original_max
} }
test {COPY basic usage for stream} { test {COPY basic usage for stream} {
r del mystream mynewstream r del mystream{t} mynewstream{t}
for {set i 0} {$i < 1000} {incr i} { for {set i 0} {$i < 1000} {incr i} {
r XADD mystream * item 2 value b r XADD mystream{t} * item 2 value b
} }
r copy mystream mynewstream r copy mystream{t} mynewstream{t}
set digest [r debug digest-value mystream] set digest [debug_digest_value mystream{t}]
assert_equal $digest [r debug digest-value mynewstream] assert_equal $digest [debug_digest_value mynewstream{t}]
assert_equal 1 [r object refcount mystream] assert_equal 1 [r object refcount mystream{t}]
assert_equal 1 [r object refcount mynewstream] assert_equal 1 [r object refcount mynewstream{t}]
r del mystream r del mystream{t}
assert_equal $digest [r debug digest-value mynewstream] assert_equal $digest [debug_digest_value mynewstream{t}]
} }
test {COPY basic usage for stream-cgroups} { test {COPY basic usage for stream-cgroups} {
r del x r del x{t}
r XADD x 100 a 1 r XADD x{t} 100 a 1
set id [r XADD x 101 b 1] set id [r XADD x{t} 101 b 1]
r XADD x 102 c 1 r XADD x{t} 102 c 1
r XADD x 103 e 1 r XADD x{t} 103 e 1
r XADD x 104 f 1 r XADD x{t} 104 f 1
r XADD x 105 g 1 r XADD x{t} 105 g 1
r XGROUP CREATE x g1 0 r XGROUP CREATE x{t} g1 0
r XGROUP CREATE x g2 0 r XGROUP CREATE x{t} g2 0
r XREADGROUP GROUP g1 Alice COUNT 1 STREAMS x > r XREADGROUP GROUP g1 Alice COUNT 1 STREAMS x{t} >
r XREADGROUP GROUP g1 Bob COUNT 1 STREAMS x > r XREADGROUP GROUP g1 Bob COUNT 1 STREAMS x{t} >
r XREADGROUP GROUP g1 Bob NOACK COUNT 1 STREAMS x > r XREADGROUP GROUP g1 Bob NOACK COUNT 1 STREAMS x{t} >
r XREADGROUP GROUP g2 Charlie COUNT 4 STREAMS x > r XREADGROUP GROUP g2 Charlie COUNT 4 STREAMS x{t} >
r XGROUP SETID x g1 $id r XGROUP SETID x{t} g1 $id
r XREADGROUP GROUP g1 Dave COUNT 3 STREAMS x > r XREADGROUP GROUP g1 Dave COUNT 3 STREAMS x{t} >
r XDEL x 103 r XDEL x{t} 103
r copy x newx r copy x{t} newx{t}
set info [r xinfo stream x full] set info [r xinfo stream x{t} full]
assert_equal $info [r xinfo stream newx full] assert_equal $info [r xinfo stream newx{t} full]
assert_equal 1 [r object refcount x] assert_equal 1 [r object refcount x{t}]
assert_equal 1 [r object refcount newx] assert_equal 1 [r object refcount newx{t}]
r del x r del x{t}
assert_equal $info [r xinfo stream newx full] assert_equal $info [r xinfo stream newx{t} full]
r flushdb r flushdb
} }
...@@ -387,18 +397,18 @@ start_server {tags {"keyspace"}} { ...@@ -387,18 +397,18 @@ start_server {tags {"keyspace"}} {
lappend res [r dbsize] lappend res [r dbsize]
r select 9 r select 9
format $res format $res
} [list 0 0 foobar 1] } [list 0 0 foobar 1] {singledb:skip}
test {MOVE against key existing in the target DB} { test {MOVE against key existing in the target DB} {
r set mykey hello r set mykey hello
r move mykey 10 r move mykey 10
} {0} } {0} {singledb:skip}
test {MOVE against non-integer DB (#1428)} { test {MOVE against non-integer DB (#1428)} {
r set mykey hello r set mykey hello
catch {r move mykey notanumber} e catch {r move mykey notanumber} e
set e set e
} {ERR value is not an integer or out of range} } {ERR value is not an integer or out of range} {singledb:skip}
test {MOVE can move key expire metadata as well} { test {MOVE can move key expire metadata as well} {
r select 10 r select 10
...@@ -411,7 +421,7 @@ start_server {tags {"keyspace"}} { ...@@ -411,7 +421,7 @@ start_server {tags {"keyspace"}} {
assert {[r ttl mykey] > 0 && [r ttl mykey] <= 100} assert {[r ttl mykey] > 0 && [r ttl mykey] <= 100}
assert {[r get mykey] eq "foo"} assert {[r get mykey] eq "foo"}
r select 9 r select 9
} } {OK} {singledb:skip}
test {MOVE does not create an expire if it does not exist} { test {MOVE does not create an expire if it does not exist} {
r select 10 r select 10
...@@ -424,7 +434,7 @@ start_server {tags {"keyspace"}} { ...@@ -424,7 +434,7 @@ start_server {tags {"keyspace"}} {
assert {[r ttl mykey] == -1} assert {[r ttl mykey] == -1}
assert {[r get mykey] eq "foo"} assert {[r get mykey] eq "foo"}
r select 9 r select 9
} } {OK} {singledb:skip}
test {SET/GET keys in different DBs} { test {SET/GET keys in different DBs} {
r set a hello r set a hello
...@@ -441,7 +451,7 @@ start_server {tags {"keyspace"}} { ...@@ -441,7 +451,7 @@ start_server {tags {"keyspace"}} {
lappend res [r get b] lappend res [r get b]
r select 9 r select 9
format $res format $res
} {hello world foo bared} } {hello world foo bared} {singledb:skip}
test {RANDOMKEY} { test {RANDOMKEY} {
r flushdb r flushdb
......
start_server {tags {"latency-monitor"}} { start_server {tags {"latency-monitor needs:latency"}} {
# Set a threshold high enough to avoid spurious latency events. # Set a threshold high enough to avoid spurious latency events.
r config set latency-monitor-threshold 200 r config set latency-monitor-threshold 200
r latency reset r latency reset
......
...@@ -67,7 +67,7 @@ start_server {tags {"lazyfree"}} { ...@@ -67,7 +67,7 @@ start_server {tags {"lazyfree"}} {
fail "lazyfree isn't done" fail "lazyfree isn't done"
} }
assert_equal [s lazyfreed_objects] 1 assert_equal [s lazyfreed_objects] 1
} } {} {needs:config-resetstat}
test "lazy free a stream with deleted cgroup" { test "lazy free a stream with deleted cgroup" {
r config resetstat r config resetstat
...@@ -83,5 +83,5 @@ start_server {tags {"lazyfree"}} { ...@@ -83,5 +83,5 @@ start_server {tags {"lazyfree"}} {
fail "lazyfree isn't done" fail "lazyfree isn't done"
} }
assert_equal [s lazyfreed_objects] 0 assert_equal [s lazyfreed_objects] 0
} } {} {needs:config-resetstat}
} }
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