diff options
author | Guy Korland <gkorland@gmail.com> | 2019-10-20 09:59:23 +0300 |
---|---|---|
committer | Guy Korland <gkorland@gmail.com> | 2019-10-20 09:59:23 +0300 |
commit | 1ac30300f027c334aa044a6f579562e52f43f26b (patch) | |
tree | d36b9c30601f7460f643842e2dee5aeb27dd7903 /tests/unit/moduleapi | |
parent | c1455dc06025259dc662144f3ca668d88789f9c0 (diff) | |
parent | 673c9d702962a5618650108eaf4c5f38bcafe164 (diff) | |
download | redis-1ac30300f027c334aa044a6f579562e52f43f26b.tar.gz |
Merge branch 'unstable' of github.com:antirez/redis into unstable
Diffstat (limited to 'tests/unit/moduleapi')
-rw-r--r-- | tests/unit/moduleapi/commandfilter.tcl | 84 | ||||
-rw-r--r-- | tests/unit/moduleapi/fork.tcl | 32 | ||||
-rw-r--r-- | tests/unit/moduleapi/infotest.tcl | 63 | ||||
-rw-r--r-- | tests/unit/moduleapi/propagate.tcl | 30 | ||||
-rw-r--r-- | tests/unit/moduleapi/testrdb.tcl | 122 |
5 files changed, 331 insertions, 0 deletions
diff --git a/tests/unit/moduleapi/commandfilter.tcl b/tests/unit/moduleapi/commandfilter.tcl new file mode 100644 index 000000000..6078f64f2 --- /dev/null +++ b/tests/unit/moduleapi/commandfilter.tcl @@ -0,0 +1,84 @@ +set testmodule [file normalize tests/modules/commandfilter.so] + +start_server {tags {"modules"}} { + r module load $testmodule log-key 0 + + test {Command Filter handles redirected commands} { + r set mykey @log + r lrange log-key 0 -1 + } "{set mykey @log}" + + test {Command Filter can call RedisModule_CommandFilterArgDelete} { + r rpush mylist elem1 @delme elem2 + r lrange mylist 0 -1 + } {elem1 elem2} + + test {Command Filter can call RedisModule_CommandFilterArgInsert} { + r del mylist + r rpush mylist elem1 @insertbefore elem2 @insertafter elem3 + r lrange mylist 0 -1 + } {elem1 --inserted-before-- @insertbefore elem2 @insertafter --inserted-after-- elem3} + + test {Command Filter can call RedisModule_CommandFilterArgReplace} { + r del mylist + r rpush mylist elem1 @replaceme elem2 + r lrange mylist 0 -1 + } {elem1 --replaced-- elem2} + + test {Command Filter applies on RM_Call() commands} { + r del log-key + r commandfilter.ping + r lrange log-key 0 -1 + } "{ping @log}" + + test {Command Filter applies on Lua redis.call()} { + r del log-key + r eval "redis.call('ping', '@log')" 0 + r lrange log-key 0 -1 + } "{ping @log}" + + test {Command Filter applies on Lua redis.call() that calls a module} { + r del log-key + r eval "redis.call('commandfilter.ping')" 0 + r lrange log-key 0 -1 + } "{ping @log}" + + test {Command Filter is unregistered implicitly on module unload} { + r del log-key + r module unload commandfilter + r set mykey @log + r lrange log-key 0 -1 + } {} + + r module load $testmodule log-key 0 + + test {Command Filter unregister works as expected} { + # Validate reloading succeeded + r del log-key + r set mykey @log + assert_equal "{set mykey @log}" [r lrange log-key 0 -1] + + # Unregister + r commandfilter.unregister + r del log-key + + r set mykey @log + r lrange log-key 0 -1 + } {} + + r module unload commandfilter + r module load $testmodule log-key 1 + + test {Command Filter REDISMODULE_CMDFILTER_NOSELF works as expected} { + r set mykey @log + assert_equal "{set mykey @log}" [r lrange log-key 0 -1] + + r del log-key + r commandfilter.ping + assert_equal {} [r lrange log-key 0 -1] + + r eval "redis.call('commandfilter.ping')" 0 + assert_equal {} [r lrange log-key 0 -1] + } + +} diff --git a/tests/unit/moduleapi/fork.tcl b/tests/unit/moduleapi/fork.tcl new file mode 100644 index 000000000..f7d7e47d5 --- /dev/null +++ b/tests/unit/moduleapi/fork.tcl @@ -0,0 +1,32 @@ +set testmodule [file normalize tests/modules/fork.so] + +proc count_log_message {pattern} { + set result [exec grep -c $pattern < [srv 0 stdout]] +} + +start_server {tags {"modules"}} { + r module load $testmodule + + test {Module fork} { + # the argument to fork.create is the exitcode on termination + r fork.create 3 + wait_for_condition 20 100 { + [r fork.exitcode] != -1 + } else { + fail "fork didn't terminate" + } + r fork.exitcode + } {3} + + test {Module fork kill} { + r fork.create 3 + after 20 + r fork.kill + after 100 + + assert {[count_log_message "fork child started"] eq "2"} + assert {[count_log_message "Received SIGUSR1 in child"] eq "1"} + assert {[count_log_message "fork child exiting"] eq "1"} + } + +} diff --git a/tests/unit/moduleapi/infotest.tcl b/tests/unit/moduleapi/infotest.tcl new file mode 100644 index 000000000..659ee79d7 --- /dev/null +++ b/tests/unit/moduleapi/infotest.tcl @@ -0,0 +1,63 @@ +set testmodule [file normalize tests/modules/infotest.so] + +# Return value for INFO property +proc field {info property} { + if {[regexp "\r\n$property:(.*?)\r\n" $info _ value]} { + set _ $value + } +} + +start_server {tags {"modules"}} { + r module load $testmodule log-key 0 + + test {module info all} { + set info [r info all] + # info all does not contain modules + assert { ![string match "*Spanish*" $info] } + assert { ![string match "*infotest_*" $info] } + assert { [string match "*used_memory*" $info] } + } + + test {module info everything} { + set info [r info everything] + # info everything contains all default sections, but not ones for crash report + assert { [string match "*infotest_global*" $info] } + assert { [string match "*Spanish*" $info] } + assert { [string match "*Italian*" $info] } + assert { [string match "*used_memory*" $info] } + assert { ![string match "*Klingon*" $info] } + field $info infotest_dos + } {2} + + test {module info modules} { + set info [r info modules] + # info all does not contain modules + assert { [string match "*Spanish*" $info] } + assert { [string match "*infotest_global*" $info] } + assert { ![string match "*used_memory*" $info] } + } + + test {module info one module} { + set info [r info INFOTEST] + # info all does not contain modules + assert { [string match "*Spanish*" $info] } + assert { ![string match "*used_memory*" $info] } + field $info infotest_global + } {-2} + + test {module info one section} { + set info [r info INFOTEST_SPANISH] + assert { ![string match "*used_memory*" $info] } + assert { ![string match "*Italian*" $info] } + assert { ![string match "*infotest_global*" $info] } + field $info infotest_uno + } {one} + + test {module info dict} { + set info [r info infotest_keyspace] + set keyspace [field $info infotest_db0] + set keys [scan [regexp -inline {keys\=([\d]*)} $keyspace] keys=%d] + } {3} + + # TODO: test crash report. +} diff --git a/tests/unit/moduleapi/propagate.tcl b/tests/unit/moduleapi/propagate.tcl new file mode 100644 index 000000000..71307ce33 --- /dev/null +++ b/tests/unit/moduleapi/propagate.tcl @@ -0,0 +1,30 @@ +set testmodule [file normalize tests/modules/propagate.so] + +tags "modules" { + test {Modules can propagate in async and threaded contexts} { + start_server {} { + set replica [srv 0 client] + set replica_host [srv 0 host] + set replica_port [srv 0 port] + start_server [list overrides [list loadmodule "$testmodule"]] { + set master [srv 0 client] + set master_host [srv 0 host] + set master_port [srv 0 port] + + # Start the replication process... + $replica replicaof $master_host $master_port + wait_for_sync $replica + + after 1000 + $master propagate-test + + wait_for_condition 5000 10 { + ([$replica get timer] eq "10") && \ + ([$replica get thread] eq "10") + } else { + fail "The two counters don't match the expected value." + } + } + } + } +} diff --git a/tests/unit/moduleapi/testrdb.tcl b/tests/unit/moduleapi/testrdb.tcl new file mode 100644 index 000000000..c72570002 --- /dev/null +++ b/tests/unit/moduleapi/testrdb.tcl @@ -0,0 +1,122 @@ +set testmodule [file normalize tests/modules/testrdb.so] + +proc restart_and_wait {} { + catch { + r debug restart + } + + # wait for the server to come back up + set retry 50 + while {$retry} { + if {[catch { r ping }]} { + after 100 + } else { + break + } + incr retry -1 + } +} + +tags "modules" { + start_server [list overrides [list loadmodule "$testmodule"]] { + test {modules are able to persist types} { + r testrdb.set.key key1 value1 + assert_equal "value1" [r testrdb.get.key key1] + r debug reload + assert_equal "value1" [r testrdb.get.key key1] + } + + test {modules global are lost without aux} { + r testrdb.set.before global1 + assert_equal "global1" [r testrdb.get.before] + restart_and_wait + assert_equal "" [r testrdb.get.before] + } + } + + start_server [list overrides [list loadmodule "$testmodule 2"]] { + test {modules are able to persist globals before and after} { + r testrdb.set.before global1 + r testrdb.set.after global2 + assert_equal "global1" [r testrdb.get.before] + assert_equal "global2" [r testrdb.get.after] + restart_and_wait + assert_equal "global1" [r testrdb.get.before] + assert_equal "global2" [r testrdb.get.after] + } + + } + + start_server [list overrides [list loadmodule "$testmodule 1"]] { + test {modules are able to persist globals just after} { + r testrdb.set.after global2 + assert_equal "global2" [r testrdb.get.after] + restart_and_wait + assert_equal "global2" [r testrdb.get.after] + } + } + + tags {repl} { + test {diskless loading short read with module} { + start_server [list overrides [list loadmodule "$testmodule"]] { + set replica [srv 0 client] + set replica_host [srv 0 host] + set replica_port [srv 0 port] + start_server [list overrides [list loadmodule "$testmodule"]] { + set master [srv 0 client] + set master_host [srv 0 host] + set master_port [srv 0 port] + + # Set master and replica to use diskless replication + $master config set repl-diskless-sync yes + $master config set rdbcompression no + $replica config set repl-diskless-load swapdb + for {set k 0} {$k < 30} {incr k} { + r testrdb.set.key key$k [string repeat A [expr {int(rand()*1000000)}]] + } + + # Start the replication process... + $master config set repl-diskless-sync-delay 0 + $replica replicaof $master_host $master_port + + # kill the replication at various points + set attempts 3 + if {$::accurate} { set attempts 10 } + for {set i 0} {$i < $attempts} {incr i} { + # wait for the replica to start reading the rdb + # using the log file since the replica only responds to INFO once in 2mb + wait_for_log_message -1 "*Loading DB in memory*" 5 2000 1 + + # add some additional random sleep so that we kill the master on a different place each time + after [expr {int(rand()*100)}] + + # kill the replica connection on the master + set killed [$master client kill type replica] + + if {[catch { + set res [wait_for_log_message -1 "*Internal error in RDB*" 5 100 10] + if {$::verbose} { + puts $res + } + }]} { + puts "failed triggering short read" + # force the replica to try another full sync + $master client kill type replica + $master set asdf asdf + # the side effect of resizing the backlog is that it is flushed (16k is the min size) + $master config set repl-backlog-size [expr {16384 + $i}] + } + # wait for loading to stop (fail) + wait_for_condition 100 10 { + [s -1 loading] eq 0 + } else { + fail "Replica didn't disconnect" + } + } + # enable fast shutdown + $master config set rdb-key-save-delay 0 + } + } + } + } +} |