summaryrefslogtreecommitdiffstats
path: root/tests/unit/moduleapi/commandfilter.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit/moduleapi/commandfilter.tcl')
-rw-r--r--tests/unit/moduleapi/commandfilter.tcl175
1 files changed, 175 insertions, 0 deletions
diff --git a/tests/unit/moduleapi/commandfilter.tcl b/tests/unit/moduleapi/commandfilter.tcl
new file mode 100644
index 0000000..72b16ec
--- /dev/null
+++ b/tests/unit/moduleapi/commandfilter.tcl
@@ -0,0 +1,175 @@
+set testmodule [file normalize tests/modules/commandfilter.so]
+
+start_server {tags {"modules"}} {
+ r module load $testmodule log-key 0
+
+ test {Retain a command filter argument} {
+ # Retain an argument now. Later we'll try to re-read it and make sure
+ # it is not corrupt and that valgrind does not complain.
+ r rpush some-list @retain my-retained-string
+ r commandfilter.retained
+ } {my-retained-string}
+
+ 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 strings can be retained} {
+ r commandfilter.retained
+ } {my-retained-string}
+
+ 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]
+ }
+
+ test "Unload the module - commandfilter" {
+ assert_equal {OK} [r module unload commandfilter]
+ }
+}
+
+test {RM_CommandFilterArgInsert and script argv caching} {
+ # coverage for scripts calling commands that expand the argv array
+ # an attempt to add coverage for a possible bug in luaArgsToRedisArgv
+ # this test needs a fresh server so that lua_argv_size is 0.
+ # glibc realloc can return the same pointer even when the size changes
+ # still this test isn't able to trigger the issue, but we keep it anyway.
+ start_server {tags {"modules"}} {
+ r module load $testmodule log-key 0
+ r del mylist
+ # command with 6 args
+ r eval {redis.call('rpush', KEYS[1], 'elem1', 'elem2', 'elem3', 'elem4')} 1 mylist
+ # command with 3 args that is changed to 4
+ r eval {redis.call('rpush', KEYS[1], '@insertafter')} 1 mylist
+ # command with 6 args again
+ r eval {redis.call('rpush', KEYS[1], 'elem1', 'elem2', 'elem3', 'elem4')} 1 mylist
+ assert_equal [r lrange mylist 0 -1] {elem1 elem2 elem3 elem4 @insertafter --inserted-after-- elem1 elem2 elem3 elem4}
+ }
+}
+
+# previously, there was a bug that command filters would be rerun (which would cause args to swap back)
+# this test is meant to protect against that bug
+test {Blocking Commands don't run through command filter when reprocessed} {
+ start_server {tags {"modules"}} {
+ r module load $testmodule log-key 0
+
+ r del list1{t}
+ r del list2{t}
+
+ r lpush list2{t} a b c d e
+
+ set rd [redis_deferring_client]
+ # we're asking to pop from the left, but the command filter swaps the two arguments,
+ # if it didn't swap it, we would end up with e d c b a 5 (5 being the left most of the following lpush)
+ # but since we swap the arguments, we end up with 1 e d c b a (1 being the right most of it).
+ # if the command filter would run again on unblock, they would be swapped back.
+ $rd blmove list1{t} list2{t} left right 0
+ wait_for_blocked_client
+ r lpush list1{t} 1 2 3 4 5
+ # validate that we moved the correct element with the swapped args
+ assert_equal [$rd read] 1
+ # validate that we moved the correct elements to the correct side of the list
+ assert_equal [r lpop list2{t}] 1
+
+ $rd close
+ }
+}
+
+test {Filtering based on client id} {
+ start_server {tags {"modules"}} {
+ r module load $testmodule log-key 0
+
+ set rr [redis_client]
+ set cid [$rr client id]
+ r unfilter_clientid $cid
+
+ r rpush mylist elem1 @replaceme elem2
+ assert_equal [r lrange mylist 0 -1] {elem1 --replaced-- elem2}
+
+ r del mylist
+
+ assert_equal [$rr rpush mylist elem1 @replaceme elem2] 3
+ assert_equal [r lrange mylist 0 -1] {elem1 @replaceme elem2}
+
+ $rr close
+ }
+}
+
+start_server {} {
+ test {OnLoad failure will handle un-registration} {
+ catch {r module load $testmodule log-key 0 noload}
+ r set mykey @log
+ assert_equal [r lrange log-key 0 -1] {}
+ r rpush mylist elem1 @delme elem2
+ assert_equal [r lrange mylist 0 -1] {elem1 @delme elem2}
+ }
+}