diff options
author | Oran Agra <oran@redislabs.com> | 2022-02-28 15:35:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-28 15:35:46 +0200 |
commit | d2b5a579dd8b785690aa7714df8776ffc452d242 (patch) | |
tree | 1c54c71bae68eaa44efbf89020d75399a88dee40 /tests/unit/moduleapi | |
parent | d5915a167f696644e210ee85e549c7ceb41b5791 (diff) | |
parent | 10dc57ab226155bbdbfb0b0d914e681aa346d7de (diff) | |
download | redis-d2b5a579dd8b785690aa7714df8776ffc452d242.tar.gz |
Merge pull request #10355 from oranagra/release-7.0-rc27.0-rc2
Release 7.0 RC2
Diffstat (limited to 'tests/unit/moduleapi')
-rw-r--r-- | tests/unit/moduleapi/aclcheck.tcl | 6 | ||||
-rw-r--r-- | tests/unit/moduleapi/blockedclient.tcl | 31 | ||||
-rw-r--r-- | tests/unit/moduleapi/cmdintrospection.tcl | 42 | ||||
-rw-r--r-- | tests/unit/moduleapi/getchannels.tcl | 40 | ||||
-rw-r--r-- | tests/unit/moduleapi/getkeys.tcl | 44 | ||||
-rw-r--r-- | tests/unit/moduleapi/infotest.tcl | 29 | ||||
-rw-r--r-- | tests/unit/moduleapi/keyspecs.tcl | 76 | ||||
-rw-r--r-- | tests/unit/moduleapi/subcommands.tcl | 13 | ||||
-rw-r--r-- | tests/unit/moduleapi/testrdb.tcl | 6 | ||||
-rw-r--r-- | tests/unit/moduleapi/timer.tcl | 40 |
10 files changed, 299 insertions, 28 deletions
diff --git a/tests/unit/moduleapi/aclcheck.tcl b/tests/unit/moduleapi/aclcheck.tcl index a6df4f7c9..953f4bf05 100644 --- a/tests/unit/moduleapi/aclcheck.tcl +++ b/tests/unit/moduleapi/aclcheck.tcl @@ -26,6 +26,12 @@ start_server {tags {"modules acl"}} { catch {r aclcheck.set.check.key "*" v 5} e assert_match "*DENIED KEY*" $e + assert_equal [r aclcheck.set.check.key "~" x 5] OK + assert_equal [r aclcheck.set.check.key "~" y 5] OK + assert_equal [r aclcheck.set.check.key "~" z 5] OK + catch {r aclcheck.set.check.key "~" v 5} e + assert_match "*DENIED KEY*" $e + assert_equal [r aclcheck.set.check.key "W" y 5] OK catch {r aclcheck.set.check.key "W" v 5} e assert_match "*DENIED KEY*" $e diff --git a/tests/unit/moduleapi/blockedclient.tcl b/tests/unit/moduleapi/blockedclient.tcl index 523d7ba69..ea2d6f5a4 100644 --- a/tests/unit/moduleapi/blockedclient.tcl +++ b/tests/unit/moduleapi/blockedclient.tcl @@ -180,6 +180,37 @@ start_server {tags {"modules"}} { assert_no_match "*name=myclient*" $clients } + test {module client error stats} { + r config resetstat + + # simple module command that replies with string error + assert_error "NULL reply returned" {r do_rm_call hgetalllll} + assert_equal [errorrstat NULL r] {count=1} + + # module command that replies with string error from bg thread + assert_error "NULL reply returned" {r do_bg_rm_call hgetalllll} + assert_equal [errorrstat NULL r] {count=2} + + # module command that returns an arity error + r do_rm_call set x x + assert_error "ERR wrong number of arguments for 'do_rm_call' command" {r do_rm_call} + assert_equal [errorrstat ERR r] {count=1} + + # RM_Call that propagates an error + assert_error "WRONGTYPE*" {r do_rm_call hgetall x} + assert_equal [errorrstat WRONGTYPE r] {count=1} + assert_match {*calls=1,*,rejected_calls=0,failed_calls=1} [cmdrstat hgetall r] + + # RM_Call from bg thread that propagates an error + assert_error "WRONGTYPE*" {r do_bg_rm_call hgetall x} + assert_equal [errorrstat WRONGTYPE r] {count=2} + assert_match {*calls=2,*,rejected_calls=0,failed_calls=2} [cmdrstat hgetall r] + + assert_equal [s total_error_replies] 5 + assert_match {*calls=4,*,rejected_calls=0,failed_calls=3} [cmdrstat do_rm_call r] + assert_match {*calls=2,*,rejected_calls=0,failed_calls=2} [cmdrstat do_bg_rm_call r] + } + test "Unload the module - blockedclient" { assert_equal {OK} [r module unload blockedclient] } diff --git a/tests/unit/moduleapi/cmdintrospection.tcl b/tests/unit/moduleapi/cmdintrospection.tcl new file mode 100644 index 000000000..375b3e406 --- /dev/null +++ b/tests/unit/moduleapi/cmdintrospection.tcl @@ -0,0 +1,42 @@ +set testmodule [file normalize tests/modules/cmdintrospection.so] + +start_server {tags {"modules"}} { + r module load $testmodule + + # cmdintrospection.xadd mimics XADD with regards to how + # what COMMAND exposes. There are two differences: + # + # 1. cmdintrospection.xadd (and all module commands) do not have ACL categories + # 2. cmdintrospection.xadd's `group` is "module" + # + # This tests verify that, apart from the above differences, the output of + # COMMAND INFO and COMMAND DOCS are identical for the two commands. + test "Module command introspection via COMMAND INFO" { + set redis_reply [lindex [r command info xadd] 0] + set module_reply [lindex [r command info cmdintrospection.xadd] 0] + for {set i 1} {$i < [llength $redis_reply]} {incr i} { + if {$i == 2} { + # Remove the "module" flag + set mylist [lindex $module_reply $i] + set idx [lsearch $mylist "module"] + set mylist [lreplace $mylist $idx $idx] + lset module_reply $i $mylist + } + if {$i == 6} { + # Skip ACL categories + continue + } + assert_equal [lindex $redis_reply $i] [lindex $module_reply $i] + } + } + + test "Module command introspection via COMMAND DOCS" { + set redis_reply [dict create {*}[lindex [r command docs xadd] 1]] + set module_reply [dict create {*}[lindex [r command docs cmdintrospection.xadd] 1]] + # Compare the maps. We need to pop "group" first. + dict unset redis_reply group + dict unset module_reply group + + assert_equal $redis_reply $module_reply + } +} diff --git a/tests/unit/moduleapi/getchannels.tcl b/tests/unit/moduleapi/getchannels.tcl new file mode 100644 index 000000000..e8f557dcc --- /dev/null +++ b/tests/unit/moduleapi/getchannels.tcl @@ -0,0 +1,40 @@ +set testmodule [file normalize tests/modules/getchannels.so] + +start_server {tags {"modules"}} { + r module load $testmodule + + # Channels are currently used to just validate ACLs, so test them here + r ACL setuser testuser +@all resetchannels &channel &pattern* + + test "module getchannels-api with literals - ACL" { + assert_equal "OK" [r ACL DRYRUN testuser getchannels.command subscribe literal channel subscribe literal pattern1] + assert_equal "OK" [r ACL DRYRUN testuser getchannels.command publish literal channel publish literal pattern1] + assert_equal "OK" [r ACL DRYRUN testuser getchannels.command unsubscribe literal channel unsubscribe literal pattern1] + + assert_equal "This user has no permissions to access the 'nopattern1' channel" [r ACL DRYRUN testuser getchannels.command subscribe literal channel subscribe literal nopattern1] + assert_equal "This user has no permissions to access the 'nopattern1' channel" [r ACL DRYRUN testuser getchannels.command publish literal channel subscribe literal nopattern1] + assert_equal "OK" [r ACL DRYRUN testuser getchannels.command unsubscribe literal channel unsubscribe literal nopattern1] + + assert_equal "This user has no permissions to access the 'otherchannel' channel" [r ACL DRYRUN testuser getchannels.command subscribe literal otherchannel subscribe literal pattern1] + assert_equal "This user has no permissions to access the 'otherchannel' channel" [r ACL DRYRUN testuser getchannels.command publish literal otherchannel subscribe literal pattern1] + assert_equal "OK" [r ACL DRYRUN testuser getchannels.command unsubscribe literal otherchannel unsubscribe literal pattern1] + } + + test "module getchannels-api with patterns - ACL" { + assert_equal "OK" [r ACL DRYRUN testuser getchannels.command subscribe pattern pattern*] + assert_equal "OK" [r ACL DRYRUN testuser getchannels.command publish pattern pattern*] + assert_equal "OK" [r ACL DRYRUN testuser getchannels.command unsubscribe pattern pattern*] + + assert_equal "This user has no permissions to access the 'pattern1' channel" [r ACL DRYRUN testuser getchannels.command subscribe pattern pattern1 subscribe pattern pattern*] + assert_equal "This user has no permissions to access the 'pattern1' channel" [r ACL DRYRUN testuser getchannels.command publish pattern pattern1 subscribe pattern pattern*] + assert_equal "OK" [r ACL DRYRUN testuser getchannels.command unsubscribe pattern pattern1 unsubscribe pattern pattern*] + + assert_equal "This user has no permissions to access the 'otherpattern*' channel" [r ACL DRYRUN testuser getchannels.command subscribe pattern otherpattern* subscribe pattern pattern*] + assert_equal "This user has no permissions to access the 'otherpattern*' channel" [r ACL DRYRUN testuser getchannels.command publish pattern otherpattern* subscribe pattern pattern*] + assert_equal "OK" [r ACL DRYRUN testuser getchannels.command unsubscribe pattern otherpattern* unsubscribe pattern pattern*] + } + + test "Unload the module - getchannels" { + assert_equal {OK} [r module unload getchannels] + } +} diff --git a/tests/unit/moduleapi/getkeys.tcl b/tests/unit/moduleapi/getkeys.tcl index 6061fe8cf..734c55fa2 100644 --- a/tests/unit/moduleapi/getkeys.tcl +++ b/tests/unit/moduleapi/getkeys.tcl @@ -16,32 +16,64 @@ start_server {tags {"modules"}} { r command getkeys getkeys.command arg1 arg2 key key1 arg3 key key2 key key3 } {key1 key2 key3} + test {COMMAND GETKEYS correctly reports a movable keys module command using flags} { + r command getkeys getkeys.command_with_flags arg1 arg2 key key1 arg3 key key2 key key3 + } {key1 key2 key3} + + test {COMMAND GETKEYSANDFLAGS correctly reports a movable keys module command not using flags} { + r command getkeysandflags getkeys.command arg1 arg2 key key1 arg3 key key2 + } {{key1 {RW access update}} {key2 {RW access update}}} + + test {COMMAND GETKEYSANDFLAGS correctly reports a movable keys module command using flags} { + r command getkeysandflags getkeys.command_with_flags arg1 arg2 key key1 arg3 key key2 key key3 + } {{key1 {RO access}} {key2 {RO access}} {key3 {RO access}}} + test {RM_GetCommandKeys on non-existing command} { - catch {r getkeys.introspect non-command key1 key2} e + catch {r getkeys.introspect 0 non-command key1 key2} e set _ $e } {*ENOENT*} test {RM_GetCommandKeys on built-in fixed keys command} { - r getkeys.introspect set key1 value1 + r getkeys.introspect 0 set key1 value1 } {key1} + test {RM_GetCommandKeys on built-in fixed keys command with flags} { + r getkeys.introspect 1 set key1 value1 + } {{key1 OW}} + test {RM_GetCommandKeys on EVAL} { - r getkeys.introspect eval "" 4 key1 key2 key3 key4 arg1 arg2 + r getkeys.introspect 0 eval "" 4 key1 key2 key3 key4 arg1 arg2 } {key1 key2 key3 key4} test {RM_GetCommandKeys on a movable keys module command} { - r getkeys.introspect getkeys.command arg1 arg2 key key1 arg3 key key2 key key3 + r getkeys.introspect 0 getkeys.command arg1 arg2 key key1 arg3 key key2 key key3 } {key1 key2 key3} test {RM_GetCommandKeys on a non-movable module command} { - r getkeys.introspect getkeys.fixed arg1 key1 key2 key3 arg2 + r getkeys.introspect 0 getkeys.fixed arg1 key1 key2 key3 arg2 } {key1 key2 key3} test {RM_GetCommandKeys with bad arity} { - catch {r getkeys.introspect set key} e + catch {r getkeys.introspect 0 set key} e set _ $e } {*EINVAL*} + # user that can only read from "read" keys, write to "write" keys, and read+write to "RW" keys + r ACL setuser testuser +@all %R~read* %W~write* %RW~rw* + + test "module getkeys-api - ACL" { + # legacy triple didn't provide flags, so they require both read and write + assert_equal "OK" [r ACL DRYRUN testuser getkeys.command key rw] + assert_equal "This user has no permissions to access the 'read' key" [r ACL DRYRUN testuser getkeys.command key read] + assert_equal "This user has no permissions to access the 'write' key" [r ACL DRYRUN testuser getkeys.command key write] + } + + test "module getkeys-api with flags - ACL" { + assert_equal "OK" [r ACL DRYRUN testuser getkeys.command_with_flags key rw] + assert_equal "OK" [r ACL DRYRUN testuser getkeys.command_with_flags key read] + assert_equal "This user has no permissions to access the 'write' key" [r ACL DRYRUN testuser getkeys.command_with_flags key write] + } + test "Unload the module - getkeys" { assert_equal {OK} [r module unload getkeys] } diff --git a/tests/unit/moduleapi/infotest.tcl b/tests/unit/moduleapi/infotest.tcl index 0d07aaa7e..354487a19 100644 --- a/tests/unit/moduleapi/infotest.tcl +++ b/tests/unit/moduleapi/infotest.tcl @@ -64,7 +64,7 @@ start_server {tags {"modules"}} { } test {module info one module} { - set info [r info INFOTEST] + set info [r info INFOtest] ;# test case insensitive compare # info all does not contain modules assert { [string match "*Spanish*" $info] } assert { ![string match "*used_memory*" $info] } @@ -72,7 +72,7 @@ start_server {tags {"modules"}} { } {-2} test {module info one section} { - set info [r info INFOTEST_SPANISH] + set info [r info INFOtest_SpanisH] ;# test case insensitive compare assert { ![string match "*used_memory*" $info] } assert { ![string match "*Italian*" $info] } assert { ![string match "*infotest_global*" $info] } @@ -90,6 +90,31 @@ start_server {tags {"modules"}} { assert_match {*infotest_unsafe_field:value=1*} $info } + test {module info multiply sections without all, everything, default keywords} { + set info [r info replication INFOTEST] + assert { [string match "*Spanish*" $info] } + assert { ![string match "*used_memory*" $info] } + assert { [string match "*repl_offset*" $info] } + } + + test {module info multiply sections with all keyword and modules} { + set info [r info all modules] + assert { [string match "*cluster*" $info] } + assert { [string match "*cmdstat_info*" $info] } + assert { [string match "*infotest_global*" $info] } + } + + test {module info multiply sections with everything keyword} { + set info [r info replication everything cpu] + assert { [string match "*client_recent*" $info] } + assert { [string match "*cmdstat_info*" $info] } + assert { [string match "*Italian*" $info] } + # check that we didn't get the same info twice + assert { ![string match "*used_cpu_user_children*used_cpu_user_children*" $info] } + assert { ![string match "*Italian*Italian*" $info] } + field $info infotest_dos + } {2} + test "Unload the module - infotest" { assert_equal {OK} [r module unload infotest] } diff --git a/tests/unit/moduleapi/keyspecs.tcl b/tests/unit/moduleapi/keyspecs.tcl index cb9f1851a..60d3fe5d3 100644 --- a/tests/unit/moduleapi/keyspecs.tcl +++ b/tests/unit/moduleapi/keyspecs.tcl @@ -1,12 +1,26 @@ set testmodule [file normalize tests/modules/keyspecs.so] -if 0 { ; # Test suite disabled due to planned API changes start_server {tags {"modules"}} { r module load $testmodule - test "Module key specs: Legacy" { - set reply [lindex [r command info kspec.legacy] 0] - # Verify (first, last, step) + test "Module key specs: No spec, only legacy triple" { + set reply [lindex [r command info kspec.none] 0] + # Verify (first, last, step) and not movablekeys + assert_equal [lindex $reply 2] {module} + assert_equal [lindex $reply 3] 1 + assert_equal [lindex $reply 4] -1 + assert_equal [lindex $reply 5] 2 + # Verify key-spec auto-generated from the legacy triple + set keyspecs [lindex $reply 8] + assert_equal [llength $keyspecs] 1 + assert_equal [lindex $keyspecs 0] {flags {RW access update variable_flags} begin_search {type index spec {index 1}} find_keys {type range spec {lastkey -1 keystep 2 limit 0}}} + assert_equal [r command getkeys kspec.none key1 val1 key2 val2] {key1 key2} + } + + test "Module key specs: Two ranges" { + set reply [lindex [r command info kspec.tworanges] 0] + # Verify (first, last, step) and not movablekeys + assert_equal [lindex $reply 2] {module} assert_equal [lindex $reply 3] 1 assert_equal [lindex $reply 4] 2 assert_equal [lindex $reply 5] 1 @@ -14,24 +28,41 @@ start_server {tags {"modules"}} { set keyspecs [lindex $reply 8] assert_equal [lindex $keyspecs 0] {flags {RO access} begin_search {type index spec {index 1}} find_keys {type range spec {lastkey 0 keystep 1 limit 0}}} assert_equal [lindex $keyspecs 1] {flags {RW update} begin_search {type index spec {index 2}} find_keys {type range spec {lastkey 0 keystep 1 limit 0}}} + assert_equal [r command getkeys kspec.tworanges foo bar baz quux] {foo bar} + } + + test "Module key specs: Keyword-only spec clears the legacy triple" { + set reply [lindex [r command info kspec.keyword] 0] + # Verify (first, last, step) and movablekeys + assert_equal [lindex $reply 2] {module movablekeys} + assert_equal [lindex $reply 3] 0 + assert_equal [lindex $reply 4] 0 + assert_equal [lindex $reply 5] 0 + # Verify key-specs + set keyspecs [lindex $reply 8] + assert_equal [lindex $keyspecs 0] {flags {RO access} begin_search {type keyword spec {keyword KEYS startfrom 1}} find_keys {type range spec {lastkey -1 keystep 1 limit 0}}} + assert_equal [r command getkeys kspec.keyword foo KEYS bar baz] {bar baz} } test "Module key specs: Complex specs, case 1" { set reply [lindex [r command info kspec.complex1] 0] - # Verify (first, last, step) + # Verify (first, last, step) and movablekeys + assert_equal [lindex $reply 2] {module movablekeys} assert_equal [lindex $reply 3] 1 assert_equal [lindex $reply 4] 1 assert_equal [lindex $reply 5] 1 # Verify key-specs set keyspecs [lindex $reply 8] - assert_equal [lindex $keyspecs 0] {flags {} begin_search {type index spec {index 1}} find_keys {type range spec {lastkey 0 keystep 1 limit 0}}} + assert_equal [lindex $keyspecs 0] {flags RO begin_search {type index spec {index 1}} find_keys {type range spec {lastkey 0 keystep 1 limit 0}}} assert_equal [lindex $keyspecs 1] {flags {RW update} begin_search {type keyword spec {keyword STORE startfrom 2}} find_keys {type range spec {lastkey 0 keystep 1 limit 0}}} assert_equal [lindex $keyspecs 2] {flags {RO access} begin_search {type keyword spec {keyword KEYS startfrom 2}} find_keys {type keynum spec {keynumidx 0 firstkey 1 keystep 1}}} + assert_equal [r command getkeys kspec.complex1 foo dummy KEYS 1 bar baz STORE quux] {foo quux bar} } test "Module key specs: Complex specs, case 2" { set reply [lindex [r command info kspec.complex2] 0] - # Verify (first, last, step) + # Verify (first, last, step) and movablekeys + assert_equal [lindex $reply 2] {module movablekeys} assert_equal [lindex $reply 3] 1 assert_equal [lindex $reply 4] 2 assert_equal [lindex $reply 5] 1 @@ -42,17 +73,42 @@ start_server {tags {"modules"}} { assert_equal [lindex $keyspecs 2] {flags {RO access} begin_search {type index spec {index 2}} find_keys {type range spec {lastkey 0 keystep 1 limit 0}}} assert_equal [lindex $keyspecs 3] {flags {RW update} begin_search {type index spec {index 3}} find_keys {type keynum spec {keynumidx 0 firstkey 1 keystep 1}}} assert_equal [lindex $keyspecs 4] {flags {RW update} begin_search {type keyword spec {keyword MOREKEYS startfrom 5}} find_keys {type range spec {lastkey -1 keystep 1 limit 0}}} + assert_equal [r command getkeys kspec.complex2 foo bar 2 baz quux banana STORE dst dummy MOREKEYS hey ho] {dst foo bar baz quux hey ho} } test "Module command list filtering" { ;# Note: we piggyback this tcl file to test the general functionality of command list filtering set reply [r command list filterby module keyspecs] - assert_equal [lsort $reply] {kspec.complex1 kspec.complex2 kspec.legacy} + assert_equal [lsort $reply] {kspec.complex1 kspec.complex2 kspec.keyword kspec.none kspec.tworanges} + assert_equal [r command getkeys kspec.complex2 foo bar 2 baz quux banana STORE dst dummy MOREKEYS hey ho] {dst foo bar baz quux hey ho} + } + + test {COMMAND GETKEYSANDFLAGS correctly reports module key-spec without flags} { + r command getkeysandflags kspec.none key1 val1 key2 val2 + } {{key1 {RW access update variable_flags}} {key2 {RW access update variable_flags}}} + + test {COMMAND GETKEYSANDFLAGS correctly reports module key-spec flags} { + r command getkeysandflags kspec.keyword keys key1 key2 key3 + } {{key1 {RO access}} {key2 {RO access}} {key3 {RO access}}} + + # user that can only read from "read" keys, write to "write" keys, and read+write to "RW" keys + r ACL setuser testuser +@all %R~read* %W~write* %RW~rw* + + test "Module key specs: No spec, only legacy triple - ACL" { + # legacy triple didn't provide flags, so they require both read and write + assert_equal "OK" [r ACL DRYRUN testuser kspec.none rw val1] + assert_equal "This user has no permissions to access the 'read' key" [r ACL DRYRUN testuser kspec.none read val1] + assert_equal "This user has no permissions to access the 'write' key" [r ACL DRYRUN testuser kspec.none write val1] + } + + test "Module key specs: tworanges - ACL" { + assert_equal "OK" [r ACL DRYRUN testuser kspec.tworanges read write] + assert_equal "OK" [r ACL DRYRUN testuser kspec.tworanges rw rw] + assert_equal "This user has no permissions to access the 'read' key" [r ACL DRYRUN testuser kspec.tworanges rw read] + assert_equal "This user has no permissions to access the 'write' key" [r ACL DRYRUN testuser kspec.tworanges write rw] } test "Unload the module - keyspecs" { assert_equal {OK} [r module unload keyspecs] } } - -} ; # Test suite disabled diff --git a/tests/unit/moduleapi/subcommands.tcl b/tests/unit/moduleapi/subcommands.tcl index d696f9ad2..11d243243 100644 --- a/tests/unit/moduleapi/subcommands.tcl +++ b/tests/unit/moduleapi/subcommands.tcl @@ -8,20 +8,15 @@ start_server {tags {"modules"}} { set command_reply [r command info subcommands.bitarray] set first_cmd [lindex $command_reply 0] set subcmds_in_command [lsort [lindex $first_cmd 9]] - if 0 { ; # Keyspecs disabled due to planned changes in keyspec API - assert_equal [lindex $subcmds_in_command 0] {subcommands.bitarray|get -2 module 1 1 1 {} {} {{flags {RO access} begin_search {type index spec {index 1}} find_keys {type range spec {lastkey 0 keystep 1 limit 0}}}} {}} - assert_equal [lindex $subcmds_in_command 1] {subcommands.bitarray|set -2 module 1 1 1 {} {} {{flags {RW update} begin_search {type index spec {index 1}} find_keys {type range spec {lastkey 0 keystep 1 limit 0}}}} {}} - } else { ; # The same asserts without the key specs - assert_equal [lindex $subcmds_in_command 0] {subcommands.bitarray|get -2 module 0 0 0 {} {} {} {}} - assert_equal [lindex $subcmds_in_command 1] {subcommands.bitarray|set -2 module 0 0 0 {} {} {} {}} - } + assert_equal [lindex $subcmds_in_command 0] {subcommands.bitarray|get -2 module 1 1 1 {} {} {{flags {RO access} begin_search {type index spec {index 1}} find_keys {type range spec {lastkey 0 keystep 1 limit 0}}}} {}} + assert_equal [lindex $subcmds_in_command 1] {subcommands.bitarray|set -2 module 1 1 1 {} {} {{flags {RW update} begin_search {type index spec {index 1}} find_keys {type range spec {lastkey 0 keystep 1 limit 0}}}} {}} # Verify that module subcommands are displayed correctly in COMMAND DOCS set docs_reply [r command docs subcommands.bitarray] set docs [dict create {*}[lindex $docs_reply 1]] set subcmds_in_cmd_docs [dict create {*}[dict get $docs subcommands]] - assert_equal [dict get $subcmds_in_cmd_docs "subcommands.bitarray|get"] {summary {} since {} group module} - assert_equal [dict get $subcmds_in_cmd_docs "subcommands.bitarray|set"] {summary {} since {} group module} + assert_equal [dict get $subcmds_in_cmd_docs "subcommands.bitarray|get"] {group module} + assert_equal [dict get $subcmds_in_cmd_docs "subcommands.bitarray|set"] {group module} } test "Module pure-container command fails on arity error" { diff --git a/tests/unit/moduleapi/testrdb.tcl b/tests/unit/moduleapi/testrdb.tcl index 8d76a11bc..a01bcb30b 100644 --- a/tests/unit/moduleapi/testrdb.tcl +++ b/tests/unit/moduleapi/testrdb.tcl @@ -47,6 +47,12 @@ tags "modules" { } } + test {Verify module options info} { + start_server [list overrides [list loadmodule "$testmodule"]] { + assert_match "*\[handle-io-errors|handle-repl-async-load\]*" [r info modules] + } + } + tags {repl} { test {diskless loading short read with module} { start_server [list overrides [list loadmodule "$testmodule"]] { diff --git a/tests/unit/moduleapi/timer.tcl b/tests/unit/moduleapi/timer.tcl index c04f80b23..4e9dd0f09 100644 --- a/tests/unit/moduleapi/timer.tcl +++ b/tests/unit/moduleapi/timer.tcl @@ -26,6 +26,8 @@ start_server {tags {"modules"}} { assert_equal "timer-incr-key" [lindex $info 0] set remaining [lindex $info 1] assert {$remaining < 10000 && $remaining > 1} + # Stop the timer after get timer test + assert_equal 1 [r test.stoptimer $id] } test {RM_StopTimer: basic sanity} { @@ -54,7 +56,43 @@ start_server {tags {"modules"}} { assert_equal {} [r test.gettimer $id] } - test "Unload the module - timer" { + test "Module can be unloaded when timer was finished" { + r set "timer-incr-key" 0 + r test.createtimer 500 timer-incr-key + + # Make sure the Timer has not been fired + assert_equal 0 [r get timer-incr-key] + # Module can not be unloaded since the timer was ongoing + catch {r module unload timer} err + assert_match {*the module holds timer that is not fired*} $err + + # Wait to be sure timer has been finished + wait_for_condition 10 500 { + [r get timer-incr-key] == 1 + } else { + fail "Timer not fired" + } + + # Timer fired, can be unloaded now. + assert_equal {OK} [r module unload timer] + } + + test "Module can be unloaded when timer was stopped" { + r module load $testmodule + r set "timer-incr-key" 0 + set id [r test.createtimer 5000 timer-incr-key] + + # Module can not be unloaded since the timer was ongoing + catch {r module unload timer} err + assert_match {*the module holds timer that is not fired*} $err + + # Stop the timer + assert_equal 1 [r test.stoptimer $id] + + # Make sure the Timer has not been fired + assert_equal 0 [r get timer-incr-key] + + # Timer has stopped, can be unloaded now. assert_equal {OK} [r module unload timer] } } |