redict/tests/unit/moduleapi/timer.tcl
郭伟光 6b5b3ca414
forbid module to unload when it holds ongoing timer (#10187)
This is done to avoid a crash when the timer fires after the module was unloaded.
Or memory leaks in case we wanted to just ignore the timer.
It'll cause the MODULE UNLOAD command to return with an error

Co-authored-by: sundb <sundbcn@gmail.com>
2022-02-01 14:54:11 +02:00

100 lines
2.9 KiB
Tcl

set testmodule [file normalize tests/modules/timer.so]
start_server {tags {"modules"}} {
r module load $testmodule
test {RM_CreateTimer: a sequence of timers work} {
# We can't guarantee same-ms but we try using MULTI/EXEC
r multi
for {set i 0} {$i < 20} {incr i} {
r test.createtimer 10 timer-incr-key
}
r exec
after 500
assert_equal 20 [r get timer-incr-key]
}
test {RM_GetTimer: basic sanity} {
# Getting non-existing timer
assert_equal {} [r test.gettimer 0]
# Getting a real timer
set id [r test.createtimer 10000 timer-incr-key]
set info [r test.gettimer $id]
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} {
r set "timer-incr-key" 0
set id [r test.createtimer 1000 timer-incr-key]
assert_equal 1 [r test.stoptimer $id]
# Wait to be sure timer doesn't execute
after 2000
assert_equal 0 [r get timer-incr-key]
# Stop non-existing timer
assert_equal 0 [r test.stoptimer $id]
}
test {Timer appears non-existing after it fires} {
r set "timer-incr-key" 0
set id [r test.createtimer 10 timer-incr-key]
# verify timer fired
after 500
assert_equal 1 [r get timer-incr-key]
# verify id does not exist
assert_equal {} [r test.gettimer $id]
}
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]
}
}