summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorSalvatore Sanfilippo <antirez@gmail.com>2019-11-19 12:15:45 +0100
committerGitHub <noreply@github.com>2019-11-19 12:15:45 +0100
commite7144fbed86ebee06253f630c6faff14615a4935 (patch)
tree77b9b59c00ca48ae8b3a310824ee9e4d51f3b3ac /tests
parenta68c19df6c884af6dfbc198bde75878ef741faf9 (diff)
parente916058f0ba59e964f5de3dee17f46ae08f1d385 (diff)
downloadredis-e7144fbed86ebee06253f630c6faff14615a4935.tar.gz
Merge branch 'unstable' into module-long-double
Diffstat (limited to 'tests')
-rw-r--r--tests/modules/Makefile4
-rw-r--r--tests/modules/datatype.c161
-rw-r--r--tests/modules/misc.c116
-rw-r--r--tests/modules/scan.c109
-rw-r--r--tests/modules/testrdb.c5
-rw-r--r--tests/support/test.tcl39
-rw-r--r--tests/unit/moduleapi/datatype.tcl27
-rw-r--r--tests/unit/moduleapi/misc.tcl46
-rw-r--r--tests/unit/moduleapi/scan.tcl47
-rw-r--r--tests/unit/type/stream.tcl6
10 files changed, 552 insertions, 8 deletions
diff --git a/tests/modules/Makefile b/tests/modules/Makefile
index 9e27758a2..f33f9e80e 100644
--- a/tests/modules/Makefile
+++ b/tests/modules/Makefile
@@ -19,7 +19,9 @@ TEST_MODULES = \
propagate.so \
misc.so \
hooks.so \
- blockonkeys.so
+ blockonkeys.so \
+ scan.so \
+ datatype.so
.PHONY: all
diff --git a/tests/modules/datatype.c b/tests/modules/datatype.c
new file mode 100644
index 000000000..7c39ab457
--- /dev/null
+++ b/tests/modules/datatype.c
@@ -0,0 +1,161 @@
+/* This module current tests a small subset but should be extended in the future
+ * for general ModuleDataType coverage.
+ */
+
+#include "redismodule.h"
+
+static RedisModuleType *datatype = NULL;
+
+typedef struct {
+ long long intval;
+ RedisModuleString *strval;
+} DataType;
+
+static void *datatype_load(RedisModuleIO *io, int encver) {
+ (void) encver;
+
+ int intval = RedisModule_LoadSigned(io);
+ if (RedisModule_IsIOError(io)) return NULL;
+
+ RedisModuleString *strval = RedisModule_LoadString(io);
+ if (RedisModule_IsIOError(io)) return NULL;
+
+ DataType *dt = (DataType *) RedisModule_Alloc(sizeof(DataType));
+ dt->intval = intval;
+ dt->strval = strval;
+ return dt;
+}
+
+static void datatype_save(RedisModuleIO *io, void *value) {
+ DataType *dt = (DataType *) value;
+ RedisModule_SaveSigned(io, dt->intval);
+ RedisModule_SaveString(io, dt->strval);
+}
+
+static void datatype_free(void *value) {
+ if (value) {
+ DataType *dt = (DataType *) value;
+
+ if (dt->strval) RedisModule_FreeString(NULL, dt->strval);
+ RedisModule_Free(dt);
+ }
+}
+
+static int datatype_set(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc != 4) {
+ RedisModule_WrongArity(ctx);
+ return REDISMODULE_OK;
+ }
+
+ long long intval;
+
+ if (RedisModule_StringToLongLong(argv[2], &intval) != REDISMODULE_OK) {
+ RedisModule_ReplyWithError(ctx, "Invalid integr value");
+ return REDISMODULE_OK;
+ }
+
+ RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
+ DataType *dt = RedisModule_Calloc(sizeof(DataType), 1);
+ dt->intval = intval;
+ dt->strval = argv[3];
+ RedisModule_RetainString(ctx, dt->strval);
+
+ RedisModule_ModuleTypeSetValue(key, datatype, dt);
+ RedisModule_CloseKey(key);
+ RedisModule_ReplyWithSimpleString(ctx, "OK");
+
+ return REDISMODULE_OK;
+}
+
+static int datatype_restore(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc != 3) {
+ RedisModule_WrongArity(ctx);
+ return REDISMODULE_OK;
+ }
+
+ DataType *dt = RedisModule_LoadDataTypeFromString(argv[2], datatype);
+ if (!dt) {
+ RedisModule_ReplyWithError(ctx, "Invalid data");
+ return REDISMODULE_OK;
+ }
+
+ RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
+ RedisModule_ModuleTypeSetValue(key, datatype, dt);
+ RedisModule_CloseKey(key);
+ RedisModule_ReplyWithSimpleString(ctx, "OK");
+
+ return REDISMODULE_OK;
+}
+
+static int datatype_get(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc != 2) {
+ RedisModule_WrongArity(ctx);
+ return REDISMODULE_OK;
+ }
+
+ RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ);
+ DataType *dt = RedisModule_ModuleTypeGetValue(key);
+ RedisModule_CloseKey(key);
+
+ RedisModule_ReplyWithArray(ctx, 2);
+ RedisModule_ReplyWithLongLong(ctx, dt->intval);
+ RedisModule_ReplyWithString(ctx, dt->strval);
+ return REDISMODULE_OK;
+}
+
+static int datatype_dump(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc != 2) {
+ RedisModule_WrongArity(ctx);
+ return REDISMODULE_OK;
+ }
+
+ RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ);
+ DataType *dt = RedisModule_ModuleTypeGetValue(key);
+ RedisModule_CloseKey(key);
+
+ RedisModuleString *reply = RedisModule_SaveDataTypeToString(ctx, dt, datatype);
+ if (!reply) {
+ RedisModule_ReplyWithError(ctx, "Failed to save");
+ return REDISMODULE_OK;
+ }
+
+ RedisModule_ReplyWithString(ctx, reply);
+ RedisModule_FreeString(ctx, reply);
+ return REDISMODULE_OK;
+}
+
+
+int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ REDISMODULE_NOT_USED(argv);
+ REDISMODULE_NOT_USED(argc);
+
+ if (RedisModule_Init(ctx,"datatype",1,REDISMODULE_APIVER_1) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ RedisModule_SetModuleOptions(ctx, REDISMODULE_OPTIONS_HANDLE_IO_ERRORS);
+
+ RedisModuleTypeMethods datatype_methods = {
+ .version = REDISMODULE_TYPE_METHOD_VERSION,
+ .rdb_load = datatype_load,
+ .rdb_save = datatype_save,
+ .free = datatype_free,
+ };
+
+ datatype = RedisModule_CreateDataType(ctx, "test___dt", 1, &datatype_methods);
+ if (datatype == NULL)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx,"datatype.set", datatype_set,"deny-oom",1,1,1) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx,"datatype.get", datatype_get,"",1,1,1) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx,"datatype.restore", datatype_restore,"deny-oom",1,1,1) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx,"datatype.dump", datatype_dump,"",1,1,1) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ return REDISMODULE_OK;
+}
diff --git a/tests/modules/misc.c b/tests/modules/misc.c
index ba0710538..b5a032f60 100644
--- a/tests/modules/misc.c
+++ b/tests/modules/misc.c
@@ -81,6 +81,107 @@ final:
return REDISMODULE_OK;
}
+int test_flushall(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
+{
+ REDISMODULE_NOT_USED(argv);
+ REDISMODULE_NOT_USED(argc);
+ RedisModule_ResetDataset(1, 0);
+ RedisModule_ReplyWithCString(ctx, "Ok");
+ return REDISMODULE_OK;
+}
+
+int test_dbsize(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
+{
+ REDISMODULE_NOT_USED(argv);
+ REDISMODULE_NOT_USED(argc);
+ long long ll = RedisModule_DbSize(ctx);
+ RedisModule_ReplyWithLongLong(ctx, ll);
+ return REDISMODULE_OK;
+}
+
+int test_randomkey(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
+{
+ REDISMODULE_NOT_USED(argv);
+ REDISMODULE_NOT_USED(argc);
+ RedisModuleString *str = RedisModule_RandomKey(ctx);
+ RedisModule_ReplyWithString(ctx, str);
+ RedisModule_FreeString(ctx, str);
+ return REDISMODULE_OK;
+}
+
+RedisModuleKey *open_key_or_reply(RedisModuleCtx *ctx, RedisModuleString *keyname, int mode) {
+ RedisModuleKey *key = RedisModule_OpenKey(ctx, keyname, mode);
+ if (!key) {
+ RedisModule_ReplyWithError(ctx, "key not found");
+ return NULL;
+ }
+ return key;
+}
+
+int test_getlru(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
+{
+ if (argc<2) {
+ RedisModule_WrongArity(ctx);
+ return REDISMODULE_OK;
+ }
+ RedisModuleKey *key = open_key_or_reply(ctx, argv[1], REDISMODULE_READ|REDISMODULE_OPEN_KEY_NOTOUCH);
+ mstime_t lru;
+ RedisModule_GetLRU(key, &lru);
+ RedisModule_ReplyWithLongLong(ctx, lru);
+ RedisModule_CloseKey(key);
+ return REDISMODULE_OK;
+}
+
+int test_setlru(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
+{
+ if (argc<3) {
+ RedisModule_WrongArity(ctx);
+ return REDISMODULE_OK;
+ }
+ RedisModuleKey *key = open_key_or_reply(ctx, argv[1], REDISMODULE_READ|REDISMODULE_OPEN_KEY_NOTOUCH);
+ mstime_t lru;
+ if (RedisModule_StringToLongLong(argv[2], &lru) != REDISMODULE_OK) {
+ RedisModule_ReplyWithError(ctx, "invalid idle time");
+ return REDISMODULE_OK;
+ }
+ int was_set = RedisModule_SetLRU(key, lru)==REDISMODULE_OK;
+ RedisModule_ReplyWithLongLong(ctx, was_set);
+ RedisModule_CloseKey(key);
+ return REDISMODULE_OK;
+}
+
+int test_getlfu(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
+{
+ if (argc<2) {
+ RedisModule_WrongArity(ctx);
+ return REDISMODULE_OK;
+ }
+ RedisModuleKey *key = open_key_or_reply(ctx, argv[1], REDISMODULE_READ|REDISMODULE_OPEN_KEY_NOTOUCH);
+ mstime_t lfu;
+ RedisModule_GetLFU(key, &lfu);
+ RedisModule_ReplyWithLongLong(ctx, lfu);
+ RedisModule_CloseKey(key);
+ return REDISMODULE_OK;
+}
+
+int test_setlfu(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
+{
+ if (argc<3) {
+ RedisModule_WrongArity(ctx);
+ return REDISMODULE_OK;
+ }
+ RedisModuleKey *key = open_key_or_reply(ctx, argv[1], REDISMODULE_READ|REDISMODULE_OPEN_KEY_NOTOUCH);
+ mstime_t lfu;
+ if (RedisModule_StringToLongLong(argv[2], &lfu) != REDISMODULE_OK) {
+ RedisModule_ReplyWithError(ctx, "invalid freq");
+ return REDISMODULE_OK;
+ }
+ int was_set = RedisModule_SetLFU(key, lfu)==REDISMODULE_OK;
+ RedisModule_ReplyWithLongLong(ctx, was_set);
+ RedisModule_CloseKey(key);
+ return REDISMODULE_OK;
+}
+
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
REDISMODULE_NOT_USED(argv);
REDISMODULE_NOT_USED(argc);
@@ -93,5 +194,20 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx,"test.ld_conversion", test_ld_conv, "",0,0,0) == REDISMODULE_ERR)
return REDISMODULE_ERR;
+ if (RedisModule_CreateCommand(ctx,"test.flushall", test_flushall,"",0,0,0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+ if (RedisModule_CreateCommand(ctx,"test.dbsize", test_dbsize,"",0,0,0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+ if (RedisModule_CreateCommand(ctx,"test.randomkey", test_randomkey,"",0,0,0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+ if (RedisModule_CreateCommand(ctx,"test.setlru", test_setlru,"",0,0,0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+ if (RedisModule_CreateCommand(ctx,"test.getlru", test_getlru,"",0,0,0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+ if (RedisModule_CreateCommand(ctx,"test.setlfu", test_setlfu,"",0,0,0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+ if (RedisModule_CreateCommand(ctx,"test.getlfu", test_getlfu,"",0,0,0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
return REDISMODULE_OK;
}
diff --git a/tests/modules/scan.c b/tests/modules/scan.c
new file mode 100644
index 000000000..afede244b
--- /dev/null
+++ b/tests/modules/scan.c
@@ -0,0 +1,109 @@
+#include "redismodule.h"
+
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+
+typedef struct {
+ size_t nkeys;
+} scan_strings_pd;
+
+void scan_strings_callback(RedisModuleCtx *ctx, RedisModuleString* keyname, RedisModuleKey* key, void *privdata) {
+ scan_strings_pd* pd = privdata;
+ int was_opened = 0;
+ if (!key) {
+ key = RedisModule_OpenKey(ctx, keyname, REDISMODULE_READ);
+ was_opened = 1;
+ }
+
+ if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_STRING) {
+ size_t len;
+ char * data = RedisModule_StringDMA(key, &len, REDISMODULE_READ);
+ RedisModule_ReplyWithArray(ctx, 2);
+ RedisModule_ReplyWithString(ctx, keyname);
+ RedisModule_ReplyWithStringBuffer(ctx, data, len);
+ pd->nkeys++;
+ }
+ if (was_opened)
+ RedisModule_CloseKey(key);
+}
+
+int scan_strings(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
+{
+ REDISMODULE_NOT_USED(argv);
+ REDISMODULE_NOT_USED(argc);
+ scan_strings_pd pd = {
+ .nkeys = 0,
+ };
+
+ RedisModule_ReplyWithArray(ctx, REDISMODULE_POSTPONED_ARRAY_LEN);
+
+ RedisModuleScanCursor* cursor = RedisModule_ScanCursorCreate();
+ while(RedisModule_Scan(ctx, cursor, scan_strings_callback, &pd));
+ RedisModule_ScanCursorDestroy(cursor);
+
+ RedisModule_ReplySetArrayLength(ctx, pd.nkeys);
+ return REDISMODULE_OK;
+}
+
+typedef struct {
+ RedisModuleCtx *ctx;
+ size_t nreplies;
+} scan_key_pd;
+
+void scan_key_callback(RedisModuleKey *key, RedisModuleString* field, RedisModuleString* value, void *privdata) {
+ REDISMODULE_NOT_USED(key);
+ scan_key_pd* pd = privdata;
+ RedisModule_ReplyWithArray(pd->ctx, 2);
+ RedisModule_ReplyWithString(pd->ctx, field);
+ if (value)
+ RedisModule_ReplyWithString(pd->ctx, value);
+ else
+ RedisModule_ReplyWithNull(pd->ctx);
+ pd->nreplies++;
+}
+
+int scan_key(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
+{
+ if (argc != 2) {
+ RedisModule_WrongArity(ctx);
+ return REDISMODULE_OK;
+ }
+ scan_key_pd pd = {
+ .ctx = ctx,
+ .nreplies = 0,
+ };
+
+ RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ);
+ if (!key) {
+ RedisModule_ReplyWithError(ctx, "not found");
+ return REDISMODULE_OK;
+ }
+
+ RedisModule_ReplyWithArray(ctx, REDISMODULE_POSTPONED_ARRAY_LEN);
+
+ RedisModuleScanCursor* cursor = RedisModule_ScanCursorCreate();
+ while(RedisModule_ScanKey(key, cursor, scan_key_callback, &pd));
+ RedisModule_ScanCursorDestroy(cursor);
+
+ RedisModule_ReplySetArrayLength(ctx, pd.nreplies);
+ RedisModule_CloseKey(key);
+ return REDISMODULE_OK;
+}
+
+int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ REDISMODULE_NOT_USED(argv);
+ REDISMODULE_NOT_USED(argc);
+ if (RedisModule_Init(ctx, "scan", 1, REDISMODULE_APIVER_1)== REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx, "scan.scan_strings", scan_strings, "", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx, "scan.scan_key", scan_key, "", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ return REDISMODULE_OK;
+}
+
+
diff --git a/tests/modules/testrdb.c b/tests/modules/testrdb.c
index 8a262e8a7..7c04bb4ef 100644
--- a/tests/modules/testrdb.c
+++ b/tests/modules/testrdb.c
@@ -18,8 +18,11 @@ void *testrdb_type_load(RedisModuleIO *rdb, int encver) {
RedisModuleString *str = RedisModule_LoadString(rdb);
float f = RedisModule_LoadFloat(rdb);
long double ld = RedisModule_LoadLongDouble(rdb);
- if (RedisModule_IsIOError(rdb))
+ if (RedisModule_IsIOError(rdb)) {
+ RedisModuleCtx *ctx = RedisModule_GetContextFromIO(rdb);
+ RedisModule_FreeString(ctx, str);
return NULL;
+ }
/* Using the values only after checking for io errors. */
assert(count==1);
assert(encver==1);
diff --git a/tests/support/test.tcl b/tests/support/test.tcl
index 2646acecd..5e8916236 100644
--- a/tests/support/test.tcl
+++ b/tests/support/test.tcl
@@ -11,28 +11,55 @@ proc fail {msg} {
proc assert {condition} {
if {![uplevel 1 [list expr $condition]]} {
- error "assertion:Expected condition '$condition' to be true ([uplevel 1 [list subst -nocommands $condition]])"
+ set context "(context: [info frame -1])"
+ error "assertion:Expected [uplevel 1 [list subst -nocommands $condition]] $context"
}
}
proc assert_no_match {pattern value} {
if {[string match $pattern $value]} {
- error "assertion:Expected '$value' to not match '$pattern'"
+ set context "(context: [info frame -1])"
+ error "assertion:Expected '$value' to not match '$pattern' $context"
}
}
proc assert_match {pattern value} {
if {![string match $pattern $value]} {
- error "assertion:Expected '$value' to match '$pattern'"
+ set context "(context: [info frame -1])"
+ error "assertion:Expected '$value' to match '$pattern' $context"
}
}
-proc assert_equal {expected value {detail ""}} {
+proc assert_equal {value expected {detail ""}} {
if {$expected ne $value} {
if {$detail ne ""} {
- set detail " (detail: $detail)"
+ set detail "(detail: $detail)"
+ } else {
+ set detail "(context: [info frame -1])"
+ }
+ error "assertion:Expected '$value' to be equal to '$expected' $detail"
+ }
+}
+
+proc assert_lessthan {value expected {detail ""}} {
+ if {!($value < $expected)} {
+ if {$detail ne ""} {
+ set detail "(detail: $detail)"
+ } else {
+ set detail "(context: [info frame -1])"
+ }
+ error "assertion:Expected '$value' to be lessthan to '$expected' $detail"
+ }
+}
+
+proc assert_range {value min max {detail ""}} {
+ if {!($value <= $max && $value >= $min)} {
+ if {$detail ne ""} {
+ set detail "(detail: $detail)"
+ } else {
+ set detail "(context: [info frame -1])"
}
- error "assertion:Expected '$value' to be equal to '$expected'$detail"
+ error "assertion:Expected '$value' to be between to '$min' and '$max' $detail"
}
}
diff --git a/tests/unit/moduleapi/datatype.tcl b/tests/unit/moduleapi/datatype.tcl
new file mode 100644
index 000000000..c1da696d3
--- /dev/null
+++ b/tests/unit/moduleapi/datatype.tcl
@@ -0,0 +1,27 @@
+set testmodule [file normalize tests/modules/datatype.so]
+
+start_server {tags {"modules"}} {
+ r module load $testmodule
+
+ test {DataType: Test module is sane, GET/SET work.} {
+ r datatype.set dtkey 100 stringval
+ assert {[r datatype.get dtkey] eq {100 stringval}}
+ }
+
+ test {DataType: RM_SaveDataTypeToString(), RM_LoadDataTypeFromString() work} {
+ r datatype.set dtkey -1111 MyString
+ set encoded [r datatype.dump dtkey]
+
+ r datatype.restore dtkeycopy $encoded
+ assert {[r datatype.get dtkeycopy] eq {-1111 MyString}}
+ }
+
+ test {DataType: Handle truncated RM_LoadDataTypeFromString()} {
+ r datatype.set dtkey -1111 MyString
+ set encoded [r datatype.dump dtkey]
+ set truncated [string range $encoded 0 end-1]
+
+ catch {r datatype.restore dtkeycopy $truncated} e
+ set e
+ } {*Invalid*}
+}
diff --git a/tests/unit/moduleapi/misc.tcl b/tests/unit/moduleapi/misc.tcl
index 21529747b..748016f1a 100644
--- a/tests/unit/moduleapi/misc.tcl
+++ b/tests/unit/moduleapi/misc.tcl
@@ -21,4 +21,50 @@ start_server {tags {"modules"}} {
assert {[string match $ld "0.00000000000000001"]}
}
+ test {test module db commands} {
+ r set x foo
+ set key [r test.randomkey]
+ assert_equal $key "x"
+ assert_equal [r test.dbsize] 1
+ r test.flushall
+ assert_equal [r test.dbsize] 0
+ }
+
+ test {test modle lru api} {
+ r config set maxmemory-policy allkeys-lru
+ r set x foo
+ set lru [r test.getlru x]
+ assert { $lru <= 1000 }
+ set was_set [r test.setlru x 100000]
+ assert { $was_set == 1 }
+ set idle [r object idletime x]
+ assert { $idle >= 100 }
+ set lru [r test.getlru x]
+ assert { $lru >= 100000 }
+ r config set maxmemory-policy allkeys-lfu
+ set lru [r test.getlru x]
+ assert { $lru == -1 }
+ set was_set [r test.setlru x 100000]
+ assert { $was_set == 0 }
+ }
+ r config set maxmemory-policy allkeys-lru
+
+ test {test modle lfu api} {
+ r config set maxmemory-policy allkeys-lfu
+ r set x foo
+ set lfu [r test.getlfu x]
+ assert { $lfu >= 1 }
+ set was_set [r test.setlfu x 100]
+ assert { $was_set == 1 }
+ set freq [r object freq x]
+ assert { $freq <= 100 }
+ set lfu [r test.getlfu x]
+ assert { $lfu <= 100 }
+ r config set maxmemory-policy allkeys-lru
+ set lfu [r test.getlfu x]
+ assert { $lfu == -1 }
+ set was_set [r test.setlfu x 100]
+ assert { $was_set == 0 }
+ }
+
}
diff --git a/tests/unit/moduleapi/scan.tcl b/tests/unit/moduleapi/scan.tcl
new file mode 100644
index 000000000..de1672e0a
--- /dev/null
+++ b/tests/unit/moduleapi/scan.tcl
@@ -0,0 +1,47 @@
+set testmodule [file normalize tests/modules/scan.so]
+
+start_server {tags {"modules"}} {
+ r module load $testmodule
+
+ test {Module scan keyspace} {
+ # the module create a scan command with filtering which also return values
+ r set x 1
+ r set y 2
+ r set z 3
+ r hset h f v
+ lsort [r scan.scan_strings]
+ } {{x 1} {y 2} {z 3}}
+
+ test {Module scan hash ziplist} {
+ r hmset hh f1 v1 f2 v2
+ lsort [r scan.scan_key hh]
+ } {{f1 v1} {f2 v2}}
+
+ test {Module scan hash dict} {
+ r config set hash-max-ziplist-entries 2
+ r hmset hh f3 v3
+ lsort [r scan.scan_key hh]
+ } {{f1 v1} {f2 v2} {f3 v3}}
+
+ test {Module scan zset ziplist} {
+ r zadd zz 1 f1 2 f2
+ lsort [r scan.scan_key zz]
+ } {{f1 1} {f2 2}}
+
+ test {Module scan zset dict} {
+ r config set zset-max-ziplist-entries 2
+ r zadd zz 3 f3
+ lsort [r scan.scan_key zz]
+ } {{f1 1} {f2 2} {f3 3}}
+
+ test {Module scan set intset} {
+ r sadd ss 1 2
+ lsort [r scan.scan_key ss]
+ } {{1 {}} {2 {}}}
+
+ test {Module scan set dict} {
+ r config set set-max-intset-entries 2
+ r sadd ss 3
+ lsort [r scan.scan_key ss]
+ } {{1 {}} {2 {}} {3 {}}}
+}
diff --git a/tests/unit/type/stream.tcl b/tests/unit/type/stream.tcl
index aa9c5f3a9..656bac5de 100644
--- a/tests/unit/type/stream.tcl
+++ b/tests/unit/type/stream.tcl
@@ -123,6 +123,12 @@ start_server {
assert {[r xlen mystream] == $j}
}
+ test {XADD with ID 0-0} {
+ r DEL otherstream
+ catch {r XADD otherstream 0-0 k v} err
+ assert {[r EXISTS otherstream] == 0}
+ }
+
test {XRANGE COUNT works as expected} {
assert {[llength [r xrange mystream - + COUNT 10]] == 10}
}