Unverified Commit 2667c412 authored by Oran Agra's avatar Oran Agra Committed by GitHub
Browse files

Merge pull request #10829 from oranagra/release-7.0.1

Release 7.0.1
parents d375595d 595e725d
...@@ -632,4 +632,50 @@ tags {"aof external:skip"} { ...@@ -632,4 +632,50 @@ tags {"aof external:skip"} {
} result } result
assert_match "*Failed to truncate AOF*to timestamp*because it is not the last file*" $result assert_match "*Failed to truncate AOF*to timestamp*because it is not the last file*" $result
} }
start_server {overrides {appendonly yes appendfsync always}} {
test {FLUSHDB / FLUSHALL should persist in AOF} {
set aof [get_last_incr_aof_path r]
r set key value
r flushdb
r set key value2
r flushdb
# DB is empty
r flushdb
r flushdb
r flushdb
r set key value
r flushall
r set key value2
r flushall
# DBs are empty.
r flushall
r flushall
r flushall
# Assert that each FLUSHDB command is persisted even the DB is empty.
# Assert that each FLUSHALL command is persisted even the DBs are empty.
assert_aof_content $aof {
{select *}
{set key value}
{flushdb}
{set key value2}
{flushdb}
{flushdb}
{flushdb}
{flushdb}
{set key value}
{flushall}
{set key value2}
{flushall}
{flushall}
{flushall}
{flushall}
}
}
}
} }
...@@ -9,7 +9,7 @@ if {$system_name eq {darwin}} { ...@@ -9,7 +9,7 @@ if {$system_name eq {darwin}} {
} elseif {$system_name eq {linux}} { } elseif {$system_name eq {linux}} {
# Avoid the test on libmusl, which does not support backtrace # Avoid the test on libmusl, which does not support backtrace
set ldd [exec ldd src/redis-server] set ldd [exec ldd src/redis-server]
if {![string match {*libc.musl*} $ldd]} { if {![string match {*libc.*musl*} $ldd]} {
set backtrace_supported 1 set backtrace_supported 1
} }
} }
......
...@@ -278,7 +278,7 @@ start_server {overrides {save ""}} { ...@@ -278,7 +278,7 @@ start_server {overrides {save ""}} {
set current_save_keys_total [s current_save_keys_total] set current_save_keys_total [s current_save_keys_total]
if {$::verbose} { if {$::verbose} {
puts "Keys before bgsave start: current_save_keys_total" puts "Keys before bgsave start: $current_save_keys_total"
} }
# on each iteration, we will write some key to the server to trigger copy-on-write, and # on each iteration, we will write some key to the server to trigger copy-on-write, and
...@@ -366,4 +366,49 @@ start_server [list overrides [list "dir" $server_path "dbfilename" "scriptbackup ...@@ -366,4 +366,49 @@ start_server [list overrides [list "dir" $server_path "dbfilename" "scriptbackup
} }
} }
start_server {} {
test "failed bgsave prevents writes" {
r config set rdb-key-save-delay 10000000
populate 1000
r set x x
r bgsave
set pid1 [get_child_pid 0]
catch {exec kill -9 $pid1}
waitForBgsave r
# make sure a read command succeeds
assert_equal [r get x] x
# make sure a write command fails
assert_error {MISCONF *} {r set x y}
# repeate with script
assert_error {MISCONF *} {r eval {
return redis.call('set','x',1)
} 1 x
}
assert_equal {x} [r eval {
return redis.call('get','x')
} 1 x
]
# again with script using shebang
assert_error {MISCONF *} {r eval {#!lua
return redis.call('set','x',1)
} 1 x
}
assert_equal {x} [r eval {#!lua flags=no-writes
return redis.call('get','x')
} 1 x
]
r config set rdb-key-save-delay 0
r bgsave
waitForBgsave r
# server is writable again
r set x y
} {OK}
}
} ;# tags } ;# tags
...@@ -225,11 +225,45 @@ start_server {tags {"repl external:skip"}} { ...@@ -225,11 +225,45 @@ start_server {tags {"repl external:skip"}} {
} }
} }
test {FLUSHALL should replicate} { test {FLUSHDB / FLUSHALL should replicate} {
set repl [attach_to_replication_stream]
r -1 set key value
r -1 flushdb
r -1 set key value2
r -1 flushall
wait_for_ofs_sync [srv 0 client] [srv -1 client]
assert_equal [r -1 dbsize] 0
assert_equal [r 0 dbsize] 0
# DB is empty.
r -1 flushdb
r -1 flushdb
r -1 flushdb
# DBs are empty.
r -1 flushall r -1 flushall
if {$::valgrind} {after 2000} r -1 flushall
list [r -1 dbsize] [r 0 dbsize] r -1 flushall
} {0 0}
# Assert that each FLUSHDB command is replicated even the DB is empty.
# Assert that each FLUSHALL command is replicated even the DBs are empty.
assert_replication_stream $repl {
{set key value}
{flushdb}
{set key value2}
{flushall}
{flushdb}
{flushdb}
{flushdb}
{flushall}
{flushall}
{flushall}
}
close_replication_stream $repl
}
test {ROLE in master reports master with a slave} { test {ROLE in master reports master with a slave} {
set res [r -1 role] set res [r -1 role]
......
...@@ -23,7 +23,8 @@ void done_handler(int exitcode, int bysignal, void *user_data) { ...@@ -23,7 +23,8 @@ void done_handler(int exitcode, int bysignal, void *user_data) {
int fork_create(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) int fork_create(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
{ {
long long code_to_exit_with; long long code_to_exit_with;
if (argc != 2) { long long usleep_us;
if (argc != 3) {
RedisModule_WrongArity(ctx); RedisModule_WrongArity(ctx);
return REDISMODULE_OK; return REDISMODULE_OK;
} }
...@@ -34,20 +35,22 @@ int fork_create(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) ...@@ -34,20 +35,22 @@ int fork_create(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
} }
RedisModule_StringToLongLong(argv[1], &code_to_exit_with); RedisModule_StringToLongLong(argv[1], &code_to_exit_with);
RedisModule_StringToLongLong(argv[2], &usleep_us);
exitted_with_code = -1; exitted_with_code = -1;
child_pid = RedisModule_Fork(done_handler, (void*)0xdeadbeef); int fork_child_pid = RedisModule_Fork(done_handler, (void*)0xdeadbeef);
if (child_pid < 0) { if (fork_child_pid < 0) {
RedisModule_ReplyWithError(ctx, "Fork failed"); RedisModule_ReplyWithError(ctx, "Fork failed");
return REDISMODULE_OK; return REDISMODULE_OK;
} else if (child_pid > 0) { } else if (fork_child_pid > 0) {
/* parent */ /* parent */
child_pid = fork_child_pid;
RedisModule_ReplyWithLongLong(ctx, child_pid); RedisModule_ReplyWithLongLong(ctx, child_pid);
return REDISMODULE_OK; return REDISMODULE_OK;
} }
/* child */ /* child */
RedisModule_Log(ctx, "notice", "fork child started"); RedisModule_Log(ctx, "notice", "fork child started");
usleep(500000); usleep(usleep_us);
RedisModule_Log(ctx, "notice", "fork child exiting"); RedisModule_Log(ctx, "notice", "fork child exiting");
RedisModule_ExitFromChild(code_to_exit_with); RedisModule_ExitFromChild(code_to_exit_with);
/* unreachable */ /* unreachable */
......
...@@ -310,6 +310,50 @@ int test_monotonic_time(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) ...@@ -310,6 +310,50 @@ int test_monotonic_time(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
return REDISMODULE_OK; return REDISMODULE_OK;
} }
/* wrapper for RM_Call */
int test_rm_call(RedisModuleCtx *ctx, RedisModuleString **argv, int argc){
if(argc < 2){
return RedisModule_WrongArity(ctx);
}
const char* cmd = RedisModule_StringPtrLen(argv[1], NULL);
RedisModuleCallReply* rep = RedisModule_Call(ctx, cmd, "Ev", argv + 2, argc - 2);
if(!rep){
RedisModule_ReplyWithError(ctx, "NULL reply returned");
}else{
RedisModule_ReplyWithCallReply(ctx, rep);
RedisModule_FreeCallReply(rep);
}
return REDISMODULE_OK;
}
/* wrapper for RM_Call with flags */
int test_rm_call_flags(RedisModuleCtx *ctx, RedisModuleString **argv, int argc){
if(argc < 3){
return RedisModule_WrongArity(ctx);
}
/* Append Ev to the provided flags. */
RedisModuleString *flags = RedisModule_CreateStringFromString(ctx, argv[1]);
RedisModule_StringAppendBuffer(ctx, flags, "Ev", 2);
const char* flg = RedisModule_StringPtrLen(flags, NULL);
const char* cmd = RedisModule_StringPtrLen(argv[2], NULL);
RedisModuleCallReply* rep = RedisModule_Call(ctx, cmd, flg, argv + 3, argc - 3);
if(!rep){
RedisModule_ReplyWithError(ctx, "NULL reply returned");
}else{
RedisModule_ReplyWithCallReply(ctx, rep);
RedisModule_FreeCallReply(rep);
}
RedisModule_FreeString(ctx, flags);
return REDISMODULE_OK;
}
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
REDISMODULE_NOT_USED(argv); REDISMODULE_NOT_USED(argv);
REDISMODULE_NOT_USED(argc); REDISMODULE_NOT_USED(argc);
...@@ -351,6 +395,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) ...@@ -351,6 +395,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
return REDISMODULE_ERR; return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx,"test.monotonic_time", test_monotonic_time,"",0,0,0) == REDISMODULE_ERR) if (RedisModule_CreateCommand(ctx,"test.monotonic_time", test_monotonic_time,"",0,0,0) == REDISMODULE_ERR)
return REDISMODULE_ERR; return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx, "test.rm_call", test_rm_call,"allow-stale", 0, 0, 0) == REDISMODULE_ERR)
return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx, "test.rm_call_flags", test_rm_call_flags,"allow-stale", 0, 0, 0) == REDISMODULE_ERR)
return REDISMODULE_ERR;
return REDISMODULE_OK; return REDISMODULE_OK;
} }
...@@ -121,13 +121,13 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) ...@@ -121,13 +121,13 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
} }
/* On the stack to make sure we're copying them. */ /* On the stack to make sure we're copying them. */
const char *enum_vals[] = {"none", "one", "two", "three"}; const char *enum_vals[] = {"none", "five", "one", "two", "four"};
const int int_vals[] = {0, 1, 2, 4}; const int int_vals[] = {0, 5, 1, 2, 4};
if (RedisModule_RegisterEnumConfig(ctx, "enum", 1, REDISMODULE_CONFIG_DEFAULT, enum_vals, int_vals, 4, getEnumConfigCommand, setEnumConfigCommand, NULL, NULL) == REDISMODULE_ERR) { if (RedisModule_RegisterEnumConfig(ctx, "enum", 1, REDISMODULE_CONFIG_DEFAULT, enum_vals, int_vals, 5, getEnumConfigCommand, setEnumConfigCommand, NULL, NULL) == REDISMODULE_ERR) {
return REDISMODULE_ERR; return REDISMODULE_ERR;
} }
if (RedisModule_RegisterEnumConfig(ctx, "flags", 3, REDISMODULE_CONFIG_DEFAULT | REDISMODULE_CONFIG_BITFLAGS, enum_vals, int_vals, 4, getFlagsConfigCommand, setFlagsConfigCommand, NULL, NULL) == REDISMODULE_ERR) { if (RedisModule_RegisterEnumConfig(ctx, "flags", 3, REDISMODULE_CONFIG_DEFAULT | REDISMODULE_CONFIG_BITFLAGS, enum_vals, int_vals, 5, getFlagsConfigCommand, setFlagsConfigCommand, NULL, NULL) == REDISMODULE_ERR) {
return REDISMODULE_ERR; return REDISMODULE_ERR;
} }
/* Memory config here. */ /* Memory config here. */
......
...@@ -79,8 +79,10 @@ test "Sentinels (re)connection following SENTINEL SET mymaster auth-pass" { ...@@ -79,8 +79,10 @@ test "Sentinels (re)connection following SENTINEL SET mymaster auth-pass" {
restart_instance sentinel $sent2re restart_instance sentinel $sent2re
# Verify sentinel that restarted failed to connect master # Verify sentinel that restarted failed to connect master
if {![string match "*disconnected*" [dict get [S $sent2re SENTINEL MASTER mymaster] flags]]} { wait_for_condition 100 50 {
fail "Expected to be disconnected from master due to wrong password" [string match "*disconnected*" [dict get [S $sent2re SENTINEL MASTER mymaster] flags]] != 0
} else {
fail "Expected to be disconnected from master due to wrong password"
} }
# Update restarted sentinel with master password # Update restarted sentinel with master password
......
...@@ -262,16 +262,22 @@ proc create_server_config_file {filename config} { ...@@ -262,16 +262,22 @@ proc create_server_config_file {filename config} {
close $fp close $fp
} }
proc spawn_server {config_file stdout stderr} { proc spawn_server {config_file stdout stderr args} {
set cmd [list src/redis-server $config_file]
set args {*}$args
if {[llength $args] > 0} {
lappend cmd {*}$args
}
if {$::valgrind} { if {$::valgrind} {
set pid [exec valgrind --track-origins=yes --trace-children=yes --suppressions=[pwd]/src/valgrind.sup --show-reachable=no --show-possibly-lost=no --leak-check=full src/redis-server $config_file >> $stdout 2>> $stderr &] set pid [exec valgrind --track-origins=yes --trace-children=yes --suppressions=[pwd]/src/valgrind.sup --show-reachable=no --show-possibly-lost=no --leak-check=full {*}$cmd >> $stdout 2>> $stderr &]
} elseif ($::stack_logging) { } elseif ($::stack_logging) {
set pid [exec /usr/bin/env MallocStackLogging=1 MallocLogFile=/tmp/malloc_log.txt src/redis-server $config_file >> $stdout 2>> $stderr &] set pid [exec /usr/bin/env MallocStackLogging=1 MallocLogFile=/tmp/malloc_log.txt {*}$cmd >> $stdout 2>> $stderr &]
} else { } else {
# ASAN_OPTIONS environment variable is for address sanitizer. If a test # ASAN_OPTIONS environment variable is for address sanitizer. If a test
# tries to allocate huge memory area and expects allocator to return # tries to allocate huge memory area and expects allocator to return
# NULL, address sanitizer throws an error without this setting. # NULL, address sanitizer throws an error without this setting.
set pid [exec /usr/bin/env ASAN_OPTIONS=allocator_may_return_null=1 src/redis-server $config_file >> $stdout 2>> $stderr &] set pid [exec /usr/bin/env ASAN_OPTIONS=allocator_may_return_null=1 {*}$cmd >> $stdout 2>> $stderr &]
} }
if {$::wait_server} { if {$::wait_server} {
...@@ -398,6 +404,7 @@ proc start_server {options {code undefined}} { ...@@ -398,6 +404,7 @@ proc start_server {options {code undefined}} {
set overrides {} set overrides {}
set omit {} set omit {}
set tags {} set tags {}
set args {}
set keep_persistence false set keep_persistence false
# parse options # parse options
...@@ -409,6 +416,9 @@ proc start_server {options {code undefined}} { ...@@ -409,6 +416,9 @@ proc start_server {options {code undefined}} {
"overrides" { "overrides" {
set overrides $value set overrides $value
} }
"args" {
set args $value
}
"omit" { "omit" {
set omit $value set omit $value
} }
...@@ -518,7 +528,7 @@ proc start_server {options {code undefined}} { ...@@ -518,7 +528,7 @@ proc start_server {options {code undefined}} {
send_data_packet $::test_server_fd "server-spawning" "port $port" send_data_packet $::test_server_fd "server-spawning" "port $port"
set pid [spawn_server $config_file $stdout $stderr] set pid [spawn_server $config_file $stdout $stderr $args]
# check that the server actually started # check that the server actually started
set port_busy [wait_server_started $config_file $stdout $pid] set port_busy [wait_server_started $config_file $stdout $pid]
...@@ -721,7 +731,7 @@ proc restart_server {level wait_ready rotate_logs {reconnect 1} {shutdown sigter ...@@ -721,7 +731,7 @@ proc restart_server {level wait_ready rotate_logs {reconnect 1} {shutdown sigter
set config_file [dict get $srv "config_file"] set config_file [dict get $srv "config_file"]
set pid [spawn_server $config_file $stdout $stderr] set pid [spawn_server $config_file $stdout $stderr {}]
# check that the server actually started # check that the server actually started
wait_server_started $config_file $stdout $pid wait_server_started $config_file $stdout $pid
......
...@@ -126,28 +126,36 @@ proc wait_for_condition {maxtries delay e _else_ elsescript} { ...@@ -126,28 +126,36 @@ proc wait_for_condition {maxtries delay e _else_ elsescript} {
} }
} }
# try to match a value to a list of patterns that is either regex, or plain sub-string # try to match a value to a list of patterns that are either regex (starts with "/") or plain string.
proc search_pattern_list {value pattern_list {substr false}} { # The caller can specify to use only glob-pattern match
set n 0 proc search_pattern_list {value pattern_list {glob_pattern false}} {
foreach el $pattern_list { foreach el $pattern_list {
if {[string length $el] > 0 && ((!$substr && [regexp -- $el $value]) || ($substr && [string match $el $value]))} { if {[string length $el] == 0} { continue }
return $n if { $glob_pattern } {
if {[string match $el $value]} {
return 1
}
continue
}
if {[string equal / [string index $el 0]] && [regexp -- [string range $el 1 end] $value]} {
return 1
} elseif {[string equal $el $value]} {
return 1
} }
incr n
} }
return -1 return 0
} }
proc test {name code {okpattern undefined} {tags {}}} { proc test {name code {okpattern undefined} {tags {}}} {
# abort if test name in skiptests # abort if test name in skiptests
if {[search_pattern_list $name $::skiptests] >= 0} { if {[search_pattern_list $name $::skiptests]} {
incr ::num_skipped incr ::num_skipped
send_data_packet $::test_server_fd skip $name send_data_packet $::test_server_fd skip $name
return return
} }
# abort if only_tests was set but test name is not included # abort if only_tests was set but test name is not included
if {[llength $::only_tests] > 0 && [search_pattern_list $name $::only_tests] < 0} { if {[llength $::only_tests] > 0 && ![search_pattern_list $name $::only_tests]} {
incr ::num_skipped incr ::num_skipped
send_data_packet $::test_server_fd skip $name send_data_packet $::test_server_fd skip $name
return return
......
...@@ -588,15 +588,15 @@ proc print_help_screen {} { ...@@ -588,15 +588,15 @@ proc print_help_screen {} {
"--single <unit> Just execute the specified unit (see next option). This option can be repeated." "--single <unit> Just execute the specified unit (see next option). This option can be repeated."
"--verbose Increases verbosity." "--verbose Increases verbosity."
"--list-tests List all the available test units." "--list-tests List all the available test units."
"--only <test> Just execute tests that match <test> regexp. This option can be repeated." "--only <test> Just execute the specified test by test name or tests that match <test> regexp (if <test> starts with '/'). This option can be repeated."
"--skip-till <unit> Skip all units until (and including) the specified one." "--skip-till <unit> Skip all units until (and including) the specified one."
"--skipunit <unit> Skip one unit." "--skipunit <unit> Skip one unit."
"--clients <num> Number of test clients (default 16)." "--clients <num> Number of test clients (default 16)."
"--timeout <sec> Test timeout in seconds (default 20 min)." "--timeout <sec> Test timeout in seconds (default 20 min)."
"--force-failure Force the execution of a test that always fails." "--force-failure Force the execution of a test that always fails."
"--config <k> <v> Extra config file argument." "--config <k> <v> Extra config file argument."
"--skipfile <file> Name of a file containing test names or regexp patterns that should be skipped (one per line)." "--skipfile <file> Name of a file containing test names or regexp patterns (if <test> starts with '/') that should be skipped (one per line)."
"--skiptest <test> Test name or regexp pattern to skip. This option can be repeated." "--skiptest <test> Test name or regexp pattern (if <test> starts with '/') to skip. This option can be repeated."
"--tags <tags> Run only tests having specified tags or not having '-' prefixed tags." "--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."
......
...@@ -529,6 +529,13 @@ start_server {tags {"acl external:skip"}} { ...@@ -529,6 +529,13 @@ start_server {tags {"acl external:skip"}} {
assert_equal [lsearch [r acl cat stream] "get"] -1 assert_equal [lsearch [r acl cat stream] "get"] -1
} }
test "ACL requires explicit permission for scripting for EVAL_RO, EVALSHA_RO and FCALL_RO" {
r ACL SETUSER scripter on nopass +readonly
assert_equal "This user has no permissions to run the 'eval_ro' command" [r ACL DRYRUN scripter EVAL_RO "" 0]
assert_equal "This user has no permissions to run the 'evalsha_ro' command" [r ACL DRYRUN scripter EVALSHA_RO "" 0]
assert_equal "This user has no permissions to run the 'fcall_ro' command" [r ACL DRYRUN scripter FCALL_RO "" 0]
}
test {ACL #5998 regression: memory leaks adding / removing subcommands} { test {ACL #5998 regression: memory leaks adding / removing subcommands} {
r AUTH default "" r AUTH default ""
r ACL setuser newuser reset -debug +debug|a +debug|b +debug|c r ACL setuser newuser reset -debug +debug|a +debug|b +debug|c
...@@ -926,3 +933,13 @@ start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"] tags ...@@ -926,3 +933,13 @@ start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"] tags
assert_match {*Duplicate user*} $err assert_match {*Duplicate user*} $err
} {} {external:skip} } {} {external:skip}
} }
start_server {overrides {user "default on nopass ~* +@all -flushdb"} tags {acl external:skip}} {
test {ACL from config file and config rewrite} {
assert_error {NOPERM *} {r flushdb}
r config rewrite
restart_server 0 true false
assert_error {NOPERM *} {r flushdb}
}
}
...@@ -424,7 +424,7 @@ start_server {tags {"scripting repl external:skip"}} { ...@@ -424,7 +424,7 @@ start_server {tags {"scripting repl external:skip"}} {
r -1 fcall test 0 r -1 fcall test 0
} e } e
set _ $e set _ $e
} {*Can not run script with write flag on readonly replica*} } {READONLY You can't write against a read only replica.}
} }
} }
...@@ -1052,7 +1052,7 @@ start_server {tags {"scripting"}} { ...@@ -1052,7 +1052,7 @@ start_server {tags {"scripting"}} {
r config set maxmemory 1 r config set maxmemory 1
catch {[r fcall f1 1 k]} e catch {[r fcall f1 1 k]} e
assert_match {*can not run it when used memory > 'maxmemory'*} $e assert_match {OOM *when used memory > 'maxmemory'*} $e
r config set maxmemory 0 r config set maxmemory 0
} {OK} {needs:config-maxmemory} } {OK} {needs:config-maxmemory}
...@@ -1064,11 +1064,8 @@ start_server {tags {"scripting"}} { ...@@ -1064,11 +1064,8 @@ start_server {tags {"scripting"}} {
r config set maxmemory 1 r config set maxmemory 1
catch {r fcall f1 1 k} e assert_equal [r fcall f1 1 k] hello
assert_match {*can not run it when used memory > 'maxmemory'*} $e assert_equal [r fcall_ro f1 1 k] hello
catch {r fcall_ro f1 1 k} e
assert_match {*can not run it when used memory > 'maxmemory'*} $e
r config set maxmemory 0 r config set maxmemory 0
} {OK} {needs:config-maxmemory} } {OK} {needs:config-maxmemory}
...@@ -1085,12 +1082,12 @@ start_server {tags {"scripting"}} { ...@@ -1085,12 +1082,12 @@ start_server {tags {"scripting"}} {
r replicaof 127.0.0.1 1 r replicaof 127.0.0.1 1
catch {[r fcall f1 0]} e catch {[r fcall f1 0]} e
assert_match {*'allow-stale' flag is not set on the script*} $e assert_match {MASTERDOWN *} $e
assert_equal {hello} [r fcall f2 0] assert_equal {hello} [r fcall f2 0]
catch {[r fcall f3 0]} e catch {[r fcall f3 0]} e
assert_match {*Can not execute the command on a stale replica*} $e assert_match {ERR *Can not execute the command on a stale replica*} $e
assert_match {*redis_version*} [r fcall f4 0] assert_match {*redis_version*} [r fcall f4 0]
...@@ -1141,6 +1138,23 @@ start_server {tags {"scripting"}} { ...@@ -1141,6 +1138,23 @@ start_server {tags {"scripting"}} {
r function stats r function stats
} {running_script {} engines {LUA {libraries_count 1 functions_count 1}}} } {running_script {} engines {LUA {libraries_count 1 functions_count 1}}}
test {FUNCTION - test function stats on loading failure} {
r FUNCTION FLUSH
r FUNCTION load {#!lua name=test1
redis.register_function('f1', function() return 1 end)
redis.register_function('f2', function() return 1 end)
}
catch {r FUNCTION load {#!lua name=test1
redis.register_function('f3', function() return 1 end)
}} e
assert_match "*Library 'test1' already exists*" $e
r function stats
} {running_script {} engines {LUA {libraries_count 1 functions_count 2}}}
test {FUNCTION - function stats cleaned after flush} { test {FUNCTION - function stats cleaned after flush} {
r function flush r function flush
r function stats r function stats
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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