summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorSalvatore Sanfilippo <antirez@gmail.com>2019-11-19 11:08:02 +0100
committerGitHub <noreply@github.com>2019-11-19 11:08:02 +0100
commit656e40eed262f61bed8cc5535b963ae1a6b300d7 (patch)
tree8f9d8725095832ec4dc9ed42127c3fac932c9e76 /tests
parent0f8692b4646013b7d98d4b21f86da0686546d43a (diff)
parent1530a3cfc69e711dc21d84dcb194b0941e0ee02e (diff)
downloadredis-656e40eed262f61bed8cc5535b963ae1a6b300d7.tar.gz
Merge branch 'unstable' into scan_module_impl
Diffstat (limited to 'tests')
-rw-r--r--tests/modules/Makefile3
-rw-r--r--tests/modules/datatype.c161
-rw-r--r--tests/unit/moduleapi/datatype.tcl27
-rw-r--r--tests/unit/type/stream.tcl6
4 files changed, 196 insertions, 1 deletions
diff --git a/tests/modules/Makefile b/tests/modules/Makefile
index 07c3cb829..f33f9e80e 100644
--- a/tests/modules/Makefile
+++ b/tests/modules/Makefile
@@ -20,7 +20,8 @@ TEST_MODULES = \
misc.so \
hooks.so \
blockonkeys.so \
- scan.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/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/type/stream.tcl b/tests/unit/type/stream.tcl
index aa9c5f3a9..a4431c654 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 mystream
+ catch {r XADD mystream 0-0 k v} err
+ assert {[r EXISTS mystream] == 0}
+ }
+
test {XRANGE COUNT works as expected} {
assert {[llength [r xrange mystream - + COUNT 10]] == 10}
}