diff --git a/runtest-moduleapi b/runtest-moduleapi index 268506160..151e38c4f 100755 --- a/runtest-moduleapi +++ b/runtest-moduleapi @@ -29,4 +29,6 @@ $TCLSH tests/test_helper.tcl \ --single unit/moduleapi/blockedclient \ --single unit/moduleapi/moduleloadsave \ --single unit/moduleapi/getkeys \ +--single unit/moduleapi/timers \ +--config server-threads 3 \ "${@}" diff --git a/tests/modules/Makefile b/tests/modules/Makefile index a8b08ecf0..c95e54554 100644 --- a/tests/modules/Makefile +++ b/tests/modules/Makefile @@ -25,7 +25,7 @@ TEST_MODULES = \ auth.so \ keyspace_events.so \ blockedclient.so \ - getkeys.so + timers.so .PHONY: all diff --git a/tests/modules/timers.c b/tests/modules/timers.c new file mode 100644 index 000000000..62b8958ea --- /dev/null +++ b/tests/modules/timers.c @@ -0,0 +1,76 @@ +#define REDISMODULE_EXPERIMENTAL_API +#include "redismodule.h" +#include +#include +#include +#include +#include +#include + +static long current_timer_count = 0; +static long total_timer_count; + +void timerHandler(RedisModuleCtx *ctx, void *data) { + REDISMODULE_NOT_USED(data); + current_timer_count++; + RedisModule_Log(ctx, "notice", "Timer %ld went off", current_timer_count); + if (current_timer_count == total_timer_count){ + RedisModule_Log(ctx, "notice", "All timers fired successfully"); + } +} + +int elapsed(RedisModuleCtx *ctx, RedisModuleString **argv, int argc){ + REDISMODULE_NOT_USED(argc); + REDISMODULE_NOT_USED(argv); + RedisModule_ReplyWithLongLong(ctx, (long long)current_timer_count); + return REDISMODULE_OK; +} + +enum TimerOrder { + TIMERS_ASCENDING, + TIMERS_DESCENDING, + TIMERS_SAME +}; + +int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + if (RedisModule_Init(ctx,"timer-spawn",1,REDISMODULE_APIVER_1) + == REDISMODULE_ERR) return REDISMODULE_ERR; + + enum TimerOrder mode; + if (argc >= 1){ + const char * modeString = RedisModule_StringPtrLen(argv[0], NULL); + if (strcmp(modeString, "ascending") == 0){ + mode = TIMERS_ASCENDING; + } else if (strcmp(modeString, "descending") == 0){ + mode = TIMERS_DESCENDING; + } else if (strcmp(modeString, "same") == 0){ + mode = TIMERS_SAME; + } else { + RedisModule_Log(ctx, "warning", "Invalid mode specified as first argument. Valid modes are: ascending, descending, and same"); + return REDISMODULE_ERR; + } + } else { + mode = TIMERS_DESCENDING; + } + + long long user_timer_count; + total_timer_count = (argc >= 2 && RedisModule_StringToLongLong(argv[1], &user_timer_count) == REDISMODULE_OK) ? + (long)user_timer_count : 2500; + + if (RedisModule_CreateCommand(ctx,"timer.elapsed", elapsed,"",0,0,0) == REDISMODULE_ERR) + return REDISMODULE_ERR; + + for (long i = 0; i < total_timer_count; i++){ + mstime_t period; + if (mode == TIMERS_ASCENDING){ + period = i; + } else if (mode == TIMERS_DESCENDING){ + period = total_timer_count - i; + } else if (mode == TIMERS_SAME){ + period = total_timer_count; + } + RedisModule_CreateTimer(ctx, period, timerHandler, NULL); + } + + return REDISMODULE_OK; +} diff --git a/tests/unit/moduleapi/timers.tcl b/tests/unit/moduleapi/timers.tcl new file mode 100644 index 000000000..6d6113f6b --- /dev/null +++ b/tests/unit/moduleapi/timers.tcl @@ -0,0 +1,35 @@ +set testmodule [file normalize tests/modules/timers.so] +set timercount 4000 + + +tags "modules" { + test {Ascending module timers can load in correctly} { + start_server [list overrides [list loadmodule "$testmodule ascending $timercount"]] { + wait_for_condition [expr round($timercount/10)] 20 { + [r timer.elapsed] == $timercount + } else { + fail "Server failed to load in timers with ascending periods" + } + } + } + + test {Descending module timers can load in correctly} { + start_server [list overrides [list loadmodule "$testmodule descending $timercount"]] { + wait_for_condition [expr round($timercount/10)] 20 { + [r timer.elapsed] == $timercount + } else { + fail "Server failed to load in timers with descending periods" + } + } + } + + test {Module timers with the same period can load in correctly} { + start_server [list overrides [list loadmodule "$testmodule same $timercount"]] { + wait_for_condition [expr round($timercount/10)] 20 { + [r timer.elapsed] == $timercount + } else { + fail "Server failed to load in timers with the same period" + } + } + } +}