From: Heinonen Arvo Date: Thu, 12 Dec 2019 14:22:12 +0000 (+0200) Subject: Add updated version of Redis modules X-Git-Tag: 0.4.0~8 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=a9dd09828c123da4387067c38dedcb54fd348dff;p=ric-plt%2Fdbaas.git Add updated version of Redis modules Adapted from Nokia internal RCP code repository, revision 120a6bb from branch 'rcp2.0'. Changes to original: * Unit tests and checking for unit test dependencies is now disabled by default. * Unit tests can be enabled with the configure flag '--enable-unit-test' * Remove Nget and Ndel. These will be refactored and reintroduced in a later commit. * Run valgrind in UT to check for memory leaks. * For opaque types there is not need to use real redis types in UT. Instead define opaque types as dummy structs in 'tst/mock/include/redismodule.h'. * Add instructions on running UT to redismodule/README.md. * Remove dead code and unused includes. * Fix compiler warnings in UT. * Treat warnings as errors in UT. Signed-off-by: Arvo Heinonen Change-Id: I8759d1c91d0dbd8c6373b7863ea11287e2d799c2 --- diff --git a/redismodule/Makefile.am b/redismodule/Makefile.am index f2b9795..6faacad 100755 --- a/redismodule/Makefile.am +++ b/redismodule/Makefile.am @@ -8,57 +8,74 @@ BASE_LDFLAGS = libredismodule_la_SOURCES = \ include/redismodule.h\ - src/exstrings.c + src/exstrings.c libredismodule_la_CFLAGS = \ - -std=c11 -fPIC -g \ - -I${includedir} -I${top_srcdir}/include + -std=c11 -fPIC -g -Wall -Werror -Wextra \ + -DREDISMODULE_EXPERIMENTAL_API \ + -I${includedir} -I${top_srcdir}/include libredismodule_la_LDFLAGS = $(BASE_LDFLAGS) -avoid-version -module -shared #pkgincludedir = ${includedir} -#pkginclude_HEADERS = include/redismodule.h +#pkginclude_HEADERS = include/redismodule.h -clean-local: +clean-local: rm -rf ${builddir}/libredismodule.pc +if UNIT_TEST_ENABLED # UT CPP_U_TEST=$(CPP_U_TEST_LATEST) check_PROGRAMS = redismodule_ut -#TESTS = ${check_PROGRAMS} +#TESTS = ${check_PROGRAMS} redismodule_ut_SOURCES = \ - tst/mock/include/redismodule.h \ - tst/mock/include/exstringsStub.h \ src/exstrings.c \ + tst/mock/include/commonStub.h \ + tst/mock/include/exstringsStub.h \ + tst/mock/include/redismodule.h \ + tst/mock/src/commonStub.cpp \ tst/mock/src/redismoduleStub.cpp \ - tst/src/main.cpp \ - tst/src/exstrings_test.cpp + tst/src/exstrings_test.cpp \ + tst/src/main.cpp redismodule_ut_CFLAGS = \ - -std=c11 -g -Wall \ - -fprofile-arcs -ftest-coverage \ - -D__UT__ \ + -std=c11 -g -Wall \ + -fprofile-arcs -ftest-coverage \ + -D__UT__ \ + $(LIBCPPUTEST_CFLAGS) \ -I${top_srcdir}/tst/mock/include \ -I${includedir} \ -I${top_srcdir}/include \ - -I${CPP_U_TEST_LATEST}/include + -I${CPP_U_TEST_LATEST}/include \ + -Wall -Werror -Wextra redismodule_ut_CXXFLAGS = \ -std=c++11 -g -Wall \ -fprofile-arcs -ftest-coverage \ -D__UT__ \ + $(LIBCPPUTEST_CFLAGS) \ -I${top_srcdir}/tst/mock/include \ -I${includedir} \ -I${top_srcdir}/include \ - -I${CPP_U_TEST_LATEST}/include + -I${CPP_U_TEST_LATEST}/include \ + -Wall -Werror -Wextra redismodule_ut_LDFLAGS = -Wl,-rpath=${libdir} ${UT_COVERAGE_LDFLAGS} -redismodule_ut_LDADD = -L${libdir} -L${CPP_U_TEST_LATEST}/lib -lCppUTest -lCppUTestExt -lgcov +redismodule_ut_LDADD = -L${libdir} $(LIBCPPUTEST_LIBS) -lgcov + test: redismodule_ut ./run-tests.sh TESTS = run-tests.sh + +else + +test: + echo 'enable ut with configure flag: --enable-unit-test' + exit 1 + +endif #UNIT_TEST_ENABLED diff --git a/redismodule/README.md b/redismodule/README.md index 7add0a6..306edd8 100755 --- a/redismodule/README.md +++ b/redismodule/README.md @@ -3,6 +3,26 @@ This subdirectory provides implementation for the commands which are implemented as a [Redis modules](https://redis.io/topics/modules-intro). +# Compiling and UT (Unit Tests) + +To compile and install run standard automake commands +in the redismodule directory: +``` +./autogen.sh +./configure +make +make install +``` + +To run unit tests `cpputest` and `valgrind` +need to be installed as additional dependencies. +To enable and run unit tests use the commands: +``` +./autogen.sh +./configure --enable-unit-test +make test +``` + # Commands ## SETIE key value oldvalue [expiration EX seconds|PX milliseconds] diff --git a/redismodule/configure.ac b/redismodule/configure.ac index ecc73e5..a688bef 100755 --- a/redismodule/configure.ac +++ b/redismodule/configure.ac @@ -16,6 +16,15 @@ AC_PROG_CC AC_PROG_INSTALL AC_PROG_MAKE_SET +AC_ARG_ENABLE([unit-test], +[ --enable-unit-test Check for UT dependencies], +[ PKG_CHECK_MODULES([LIBCPPUTEST],[cpputest]) + AC_CHECK_PROG(VALGRIND_CHECK, valgrind, yes) + AS_IF([test x"$VALGRIND_CHECK" != x"yes"], [AC_MSG_ERROR([Install valgrind to run UT.])]) + UNIT_TEST_ENABLED=true +], +[ UNIT_TEST_ENABLED=false ]) +AM_CONDITIONAL([UNIT_TEST_ENABLED], [$UNIT_TEST_ENABLED]) # Checks for header files. diff --git a/redismodule/include/redismodule.h b/redismodule/include/redismodule.h index c6f97d5..e64b1a9 100755 --- a/redismodule/include/redismodule.h +++ b/redismodule/include/redismodule.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nokia. + * Copyright (c) 2018-2020 Nokia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -79,28 +79,37 @@ #define REDISMODULE_HASH_CFIELDS (1<<2) #define REDISMODULE_HASH_EXISTS (1<<3) -/* Context Flags: Info about the current context returned by RM_GetContextFlags */ +/* Context Flags: Info about the current context returned by + * RM_GetContextFlags(). */ /* The command is running in the context of a Lua script */ -#define REDISMODULE_CTX_FLAGS_LUA 0x0001 +#define REDISMODULE_CTX_FLAGS_LUA (1<<0) /* The command is running inside a Redis transaction */ -#define REDISMODULE_CTX_FLAGS_MULTI 0x0002 +#define REDISMODULE_CTX_FLAGS_MULTI (1<<1) /* The instance is a master */ -#define REDISMODULE_CTX_FLAGS_MASTER 0x0004 +#define REDISMODULE_CTX_FLAGS_MASTER (1<<2) /* The instance is a slave */ -#define REDISMODULE_CTX_FLAGS_SLAVE 0x0008 +#define REDISMODULE_CTX_FLAGS_SLAVE (1<<3) /* The instance is read-only (usually meaning it's a slave as well) */ -#define REDISMODULE_CTX_FLAGS_READONLY 0x0010 +#define REDISMODULE_CTX_FLAGS_READONLY (1<<4) /* The instance is running in cluster mode */ -#define REDISMODULE_CTX_FLAGS_CLUSTER 0x0020 +#define REDISMODULE_CTX_FLAGS_CLUSTER (1<<5) /* The instance has AOF enabled */ -#define REDISMODULE_CTX_FLAGS_AOF 0x0040 // +#define REDISMODULE_CTX_FLAGS_AOF (1<<6) /* The instance has RDB enabled */ -#define REDISMODULE_CTX_FLAGS_RDB 0x0080 // +#define REDISMODULE_CTX_FLAGS_RDB (1<<7) /* The instance has Maxmemory set */ -#define REDISMODULE_CTX_FLAGS_MAXMEMORY 0x0100 +#define REDISMODULE_CTX_FLAGS_MAXMEMORY (1<<8) /* Maxmemory is set and has an eviction policy that may delete keys */ -#define REDISMODULE_CTX_FLAGS_EVICT 0x0200 +#define REDISMODULE_CTX_FLAGS_EVICT (1<<9) +/* Redis is out of memory according to the maxmemory flag. */ +#define REDISMODULE_CTX_FLAGS_OOM (1<<10) +/* Less than 25% of memory available according to maxmemory. */ +#define REDISMODULE_CTX_FLAGS_OOM_WARNING (1<<11) +/* The command was sent over the replication link. */ +#define REDISMODULE_CTX_FLAGS_REPLICATED (1<<12) +/* Redis is currently loading either from AOF or RDB. */ +#define REDISMODULE_CTX_FLAGS_LOADING (1<<13) #define REDISMODULE_NOTIFY_GENERIC (1<<2) /* g */ @@ -111,7 +120,8 @@ #define REDISMODULE_NOTIFY_ZSET (1<<7) /* z */ #define REDISMODULE_NOTIFY_EXPIRED (1<<8) /* x */ #define REDISMODULE_NOTIFY_EVICTED (1<<9) /* e */ -#define REDISMODULE_NOTIFY_ALL (REDISMODULE_NOTIFY_GENERIC | REDISMODULE_NOTIFY_STRING | REDISMODULE_NOTIFY_LIST | REDISMODULE_NOTIFY_SET | REDISMODULE_NOTIFY_HASH | REDISMODULE_NOTIFY_ZSET | REDISMODULE_NOTIFY_EXPIRED | REDISMODULE_NOTIFY_EVICTED) /* A */ +#define REDISMODULE_NOTIFY_STREAM (1<<10) /* t */ +#define REDISMODULE_NOTIFY_ALL (REDISMODULE_NOTIFY_GENERIC | REDISMODULE_NOTIFY_STRING | REDISMODULE_NOTIFY_LIST | REDISMODULE_NOTIFY_SET | REDISMODULE_NOTIFY_HASH | REDISMODULE_NOTIFY_ZSET | REDISMODULE_NOTIFY_EXPIRED | REDISMODULE_NOTIFY_EVICTED | REDISMODULE_NOTIFY_STREAM) /* A */ /* A special pointer that we can use between the core and the module to signal @@ -124,8 +134,36 @@ #define REDISMODULE_POSITIVE_INFINITE (1.0/0.0) #define REDISMODULE_NEGATIVE_INFINITE (-1.0/0.0) +/* Cluster API defines. */ +#define REDISMODULE_NODE_ID_LEN 40 +#define REDISMODULE_NODE_MYSELF (1<<0) +#define REDISMODULE_NODE_MASTER (1<<1) +#define REDISMODULE_NODE_SLAVE (1<<2) +#define REDISMODULE_NODE_PFAIL (1<<3) +#define REDISMODULE_NODE_FAIL (1<<4) +#define REDISMODULE_NODE_NOFAILOVER (1<<5) + +#define REDISMODULE_CLUSTER_FLAG_NONE 0 +#define REDISMODULE_CLUSTER_FLAG_NO_FAILOVER (1<<1) +#define REDISMODULE_CLUSTER_FLAG_NO_REDIRECTION (1<<2) + #define REDISMODULE_NOT_USED(V) ((void) V) +/* Bit flags for aux_save_triggers and the aux_load and aux_save callbacks */ +#define REDISMODULE_AUX_BEFORE_RDB (1<<0) +#define REDISMODULE_AUX_AFTER_RDB (1<<1) + +/* This type represents a timer handle, and is returned when a timer is + * registered and used in order to invalidate a timer. It's just a 64 bit + * number, because this is how each timer is represented inside the radix tree + * of timers that are going to expire, sorted by expire time. */ +typedef uint64_t RedisModuleTimerID; + +/* CommandFilter Flags */ + +/* Do filter RedisModule_Call() commands initiated by module itself. */ +#define REDISMODULE_CMDFILTER_NOSELF (1<<0) + /* ------------------------- End of common defines ------------------------ */ #ifndef REDISMODULE_CORE @@ -141,18 +179,28 @@ typedef struct RedisModuleIO RedisModuleIO; typedef struct RedisModuleType RedisModuleType; typedef struct RedisModuleDigest RedisModuleDigest; typedef struct RedisModuleBlockedClient RedisModuleBlockedClient; - -typedef int (*RedisModuleCmdFunc) (RedisModuleCtx *ctx, RedisModuleString **argv, int argc); - -typedef int (*RedisModuleNotificationFunc) (RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key); +typedef struct RedisModuleClusterInfo RedisModuleClusterInfo; +typedef struct RedisModuleDict RedisModuleDict; +typedef struct RedisModuleDictIter RedisModuleDictIter; +typedef struct RedisModuleCommandFilterCtx RedisModuleCommandFilterCtx; +typedef struct RedisModuleCommandFilter RedisModuleCommandFilter; + +typedef int (*RedisModuleCmdFunc)(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); +typedef void (*RedisModuleDisconnectFunc)(RedisModuleCtx *ctx, RedisModuleBlockedClient *bc); +typedef int (*RedisModuleNotificationFunc)(RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key); typedef void *(*RedisModuleTypeLoadFunc)(RedisModuleIO *rdb, int encver); typedef void (*RedisModuleTypeSaveFunc)(RedisModuleIO *rdb, void *value); +typedef int (*RedisModuleTypeAuxLoadFunc)(RedisModuleIO *rdb, int encver, int when); +typedef void (*RedisModuleTypeAuxSaveFunc)(RedisModuleIO *rdb, int when); typedef void (*RedisModuleTypeRewriteFunc)(RedisModuleIO *aof, RedisModuleString *key, void *value); typedef size_t (*RedisModuleTypeMemUsageFunc)(const void *value); typedef void (*RedisModuleTypeDigestFunc)(RedisModuleDigest *digest, void *value); typedef void (*RedisModuleTypeFreeFunc)(void *value); +typedef void (*RedisModuleClusterMessageReceiver)(RedisModuleCtx *ctx, const char *sender_id, uint8_t type, const unsigned char *payload, uint32_t len); +typedef void (*RedisModuleTimerProc)(RedisModuleCtx *ctx, void *data); +typedef void (*RedisModuleCommandFilterFunc) (RedisModuleCommandFilterCtx *filter); -#define REDISMODULE_TYPE_METHOD_VERSION 1 +#define REDISMODULE_TYPE_METHOD_VERSION 2 typedef struct RedisModuleTypeMethods { uint64_t version; RedisModuleTypeLoadFunc rdb_load; @@ -161,6 +209,9 @@ typedef struct RedisModuleTypeMethods { RedisModuleTypeMemUsageFunc mem_usage; RedisModuleTypeDigestFunc digest; RedisModuleTypeFreeFunc free; + RedisModuleTypeAuxLoadFunc aux_load; + RedisModuleTypeAuxSaveFunc aux_save; + int aux_save_triggers; } RedisModuleTypeMethods; #define REDISMODULE_GET_API(name) \ @@ -206,6 +257,7 @@ int REDISMODULE_API_FUNC(RedisModule_ReplyWithSimpleString)(RedisModuleCtx *ctx, int REDISMODULE_API_FUNC(RedisModule_ReplyWithArray)(RedisModuleCtx *ctx, long len); void REDISMODULE_API_FUNC(RedisModule_ReplySetArrayLength)(RedisModuleCtx *ctx, long len); int REDISMODULE_API_FUNC(RedisModule_ReplyWithStringBuffer)(RedisModuleCtx *ctx, const char *buf, size_t len); +int REDISMODULE_API_FUNC(RedisModule_ReplyWithCString)(RedisModuleCtx *ctx, const char *buf); int REDISMODULE_API_FUNC(RedisModule_ReplyWithString)(RedisModuleCtx *ctx, RedisModuleString *str); int REDISMODULE_API_FUNC(RedisModule_ReplyWithNull)(RedisModuleCtx *ctx); int REDISMODULE_API_FUNC(RedisModule_ReplyWithDouble)(RedisModuleCtx *ctx, double d); @@ -267,25 +319,73 @@ int REDISMODULE_API_FUNC(RedisModule_StringAppendBuffer)(RedisModuleCtx *ctx, Re void REDISMODULE_API_FUNC(RedisModule_RetainString)(RedisModuleCtx *ctx, RedisModuleString *str); int REDISMODULE_API_FUNC(RedisModule_StringCompare)(RedisModuleString *a, RedisModuleString *b); RedisModuleCtx *REDISMODULE_API_FUNC(RedisModule_GetContextFromIO)(RedisModuleIO *io); +const RedisModuleString *REDISMODULE_API_FUNC(RedisModule_GetKeyNameFromIO)(RedisModuleIO *io); long long REDISMODULE_API_FUNC(RedisModule_Milliseconds)(void); void REDISMODULE_API_FUNC(RedisModule_DigestAddStringBuffer)(RedisModuleDigest *md, unsigned char *ele, size_t len); void REDISMODULE_API_FUNC(RedisModule_DigestAddLongLong)(RedisModuleDigest *md, long long ele); void REDISMODULE_API_FUNC(RedisModule_DigestEndSequence)(RedisModuleDigest *md); +RedisModuleDict *REDISMODULE_API_FUNC(RedisModule_CreateDict)(RedisModuleCtx *ctx); +void REDISMODULE_API_FUNC(RedisModule_FreeDict)(RedisModuleCtx *ctx, RedisModuleDict *d); +uint64_t REDISMODULE_API_FUNC(RedisModule_DictSize)(RedisModuleDict *d); +int REDISMODULE_API_FUNC(RedisModule_DictSetC)(RedisModuleDict *d, void *key, size_t keylen, void *ptr); +int REDISMODULE_API_FUNC(RedisModule_DictReplaceC)(RedisModuleDict *d, void *key, size_t keylen, void *ptr); +int REDISMODULE_API_FUNC(RedisModule_DictSet)(RedisModuleDict *d, RedisModuleString *key, void *ptr); +int REDISMODULE_API_FUNC(RedisModule_DictReplace)(RedisModuleDict *d, RedisModuleString *key, void *ptr); +void *REDISMODULE_API_FUNC(RedisModule_DictGetC)(RedisModuleDict *d, void *key, size_t keylen, int *nokey); +void *REDISMODULE_API_FUNC(RedisModule_DictGet)(RedisModuleDict *d, RedisModuleString *key, int *nokey); +int REDISMODULE_API_FUNC(RedisModule_DictDelC)(RedisModuleDict *d, void *key, size_t keylen, void *oldval); +int REDISMODULE_API_FUNC(RedisModule_DictDel)(RedisModuleDict *d, RedisModuleString *key, void *oldval); +RedisModuleDictIter *REDISMODULE_API_FUNC(RedisModule_DictIteratorStartC)(RedisModuleDict *d, const char *op, void *key, size_t keylen); +RedisModuleDictIter *REDISMODULE_API_FUNC(RedisModule_DictIteratorStart)(RedisModuleDict *d, const char *op, RedisModuleString *key); +void REDISMODULE_API_FUNC(RedisModule_DictIteratorStop)(RedisModuleDictIter *di); +int REDISMODULE_API_FUNC(RedisModule_DictIteratorReseekC)(RedisModuleDictIter *di, const char *op, void *key, size_t keylen); +int REDISMODULE_API_FUNC(RedisModule_DictIteratorReseek)(RedisModuleDictIter *di, const char *op, RedisModuleString *key); +void *REDISMODULE_API_FUNC(RedisModule_DictNextC)(RedisModuleDictIter *di, size_t *keylen, void **dataptr); +void *REDISMODULE_API_FUNC(RedisModule_DictPrevC)(RedisModuleDictIter *di, size_t *keylen, void **dataptr); +RedisModuleString *REDISMODULE_API_FUNC(RedisModule_DictNext)(RedisModuleCtx *ctx, RedisModuleDictIter *di, void **dataptr); +RedisModuleString *REDISMODULE_API_FUNC(RedisModule_DictPrev)(RedisModuleCtx *ctx, RedisModuleDictIter *di, void **dataptr); +int REDISMODULE_API_FUNC(RedisModule_DictCompareC)(RedisModuleDictIter *di, const char *op, void *key, size_t keylen); +int REDISMODULE_API_FUNC(RedisModule_DictCompare)(RedisModuleDictIter *di, const char *op, RedisModuleString *key); /* Experimental APIs */ #ifdef REDISMODULE_EXPERIMENTAL_API -RedisModuleBlockedClient *REDISMODULE_API_FUNC(RedisModule_BlockClient)(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(void*), long long timeout_ms); +#define REDISMODULE_EXPERIMENTAL_API_VERSION 3 +RedisModuleBlockedClient *REDISMODULE_API_FUNC(RedisModule_BlockClient)(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms); int REDISMODULE_API_FUNC(RedisModule_UnblockClient)(RedisModuleBlockedClient *bc, void *privdata); int REDISMODULE_API_FUNC(RedisModule_IsBlockedReplyRequest)(RedisModuleCtx *ctx); int REDISMODULE_API_FUNC(RedisModule_IsBlockedTimeoutRequest)(RedisModuleCtx *ctx); void *REDISMODULE_API_FUNC(RedisModule_GetBlockedClientPrivateData)(RedisModuleCtx *ctx); +RedisModuleBlockedClient *REDISMODULE_API_FUNC(RedisModule_GetBlockedClientHandle)(RedisModuleCtx *ctx); int REDISMODULE_API_FUNC(RedisModule_AbortBlock)(RedisModuleBlockedClient *bc); RedisModuleCtx *REDISMODULE_API_FUNC(RedisModule_GetThreadSafeContext)(RedisModuleBlockedClient *bc); void REDISMODULE_API_FUNC(RedisModule_FreeThreadSafeContext)(RedisModuleCtx *ctx); void REDISMODULE_API_FUNC(RedisModule_ThreadSafeContextLock)(RedisModuleCtx *ctx); void REDISMODULE_API_FUNC(RedisModule_ThreadSafeContextUnlock)(RedisModuleCtx *ctx); int REDISMODULE_API_FUNC(RedisModule_SubscribeToKeyspaceEvents)(RedisModuleCtx *ctx, int types, RedisModuleNotificationFunc cb); - +int REDISMODULE_API_FUNC(RedisModule_BlockedClientDisconnected)(RedisModuleCtx *ctx); +void REDISMODULE_API_FUNC(RedisModule_RegisterClusterMessageReceiver)(RedisModuleCtx *ctx, uint8_t type, RedisModuleClusterMessageReceiver callback); +int REDISMODULE_API_FUNC(RedisModule_SendClusterMessage)(RedisModuleCtx *ctx, char *target_id, uint8_t type, unsigned char *msg, uint32_t len); +int REDISMODULE_API_FUNC(RedisModule_GetClusterNodeInfo)(RedisModuleCtx *ctx, const char *id, char *ip, char *master_id, int *port, int *flags); +char **REDISMODULE_API_FUNC(RedisModule_GetClusterNodesList)(RedisModuleCtx *ctx, size_t *numnodes); +void REDISMODULE_API_FUNC(RedisModule_FreeClusterNodesList)(char **ids); +RedisModuleTimerID REDISMODULE_API_FUNC(RedisModule_CreateTimer)(RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data); +int REDISMODULE_API_FUNC(RedisModule_StopTimer)(RedisModuleCtx *ctx, RedisModuleTimerID id, void **data); +int REDISMODULE_API_FUNC(RedisModule_GetTimerInfo)(RedisModuleCtx *ctx, RedisModuleTimerID id, uint64_t *remaining, void **data); +const char *REDISMODULE_API_FUNC(RedisModule_GetMyClusterID)(void); +size_t REDISMODULE_API_FUNC(RedisModule_GetClusterSize)(void); +void REDISMODULE_API_FUNC(RedisModule_GetRandomBytes)(unsigned char *dst, size_t len); +void REDISMODULE_API_FUNC(RedisModule_GetRandomHexChars)(char *dst, size_t len); +void REDISMODULE_API_FUNC(RedisModule_SetDisconnectCallback)(RedisModuleBlockedClient *bc, RedisModuleDisconnectFunc callback); +void REDISMODULE_API_FUNC(RedisModule_SetClusterFlags)(RedisModuleCtx *ctx, uint64_t flags); +int REDISMODULE_API_FUNC(RedisModule_ExportSharedAPI)(RedisModuleCtx *ctx, const char *apiname, void *func); +void *REDISMODULE_API_FUNC(RedisModule_GetSharedAPI)(RedisModuleCtx *ctx, const char *apiname); +RedisModuleCommandFilter *REDISMODULE_API_FUNC(RedisModule_RegisterCommandFilter)(RedisModuleCtx *ctx, RedisModuleCommandFilterFunc cb, int flags); +int REDISMODULE_API_FUNC(RedisModule_UnregisterCommandFilter)(RedisModuleCtx *ctx, RedisModuleCommandFilter *filter); +int REDISMODULE_API_FUNC(RedisModule_CommandFilterArgsCount)(RedisModuleCommandFilterCtx *fctx); +const RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CommandFilterArgGet)(RedisModuleCommandFilterCtx *fctx, int pos); +int REDISMODULE_API_FUNC(RedisModule_CommandFilterArgInsert)(RedisModuleCommandFilterCtx *fctx, int pos, RedisModuleString *arg); +int REDISMODULE_API_FUNC(RedisModule_CommandFilterArgReplace)(RedisModuleCommandFilterCtx *fctx, int pos, RedisModuleString *arg); +int REDISMODULE_API_FUNC(RedisModule_CommandFilterArgDelete)(RedisModuleCommandFilterCtx *fctx, int pos); #endif /* This is included inline inside each Redis module. */ @@ -308,6 +408,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(ReplyWithArray); REDISMODULE_GET_API(ReplySetArrayLength); REDISMODULE_GET_API(ReplyWithStringBuffer); + REDISMODULE_GET_API(ReplyWithCString); REDISMODULE_GET_API(ReplyWithString); REDISMODULE_GET_API(ReplyWithNull); REDISMODULE_GET_API(ReplyWithCallReply); @@ -391,10 +492,33 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(RetainString); REDISMODULE_GET_API(StringCompare); REDISMODULE_GET_API(GetContextFromIO); + REDISMODULE_GET_API(GetKeyNameFromIO); REDISMODULE_GET_API(Milliseconds); REDISMODULE_GET_API(DigestAddStringBuffer); REDISMODULE_GET_API(DigestAddLongLong); REDISMODULE_GET_API(DigestEndSequence); + REDISMODULE_GET_API(CreateDict); + REDISMODULE_GET_API(FreeDict); + REDISMODULE_GET_API(DictSize); + REDISMODULE_GET_API(DictSetC); + REDISMODULE_GET_API(DictReplaceC); + REDISMODULE_GET_API(DictSet); + REDISMODULE_GET_API(DictReplace); + REDISMODULE_GET_API(DictGetC); + REDISMODULE_GET_API(DictGet); + REDISMODULE_GET_API(DictDelC); + REDISMODULE_GET_API(DictDel); + REDISMODULE_GET_API(DictIteratorStartC); + REDISMODULE_GET_API(DictIteratorStart); + REDISMODULE_GET_API(DictIteratorStop); + REDISMODULE_GET_API(DictIteratorReseekC); + REDISMODULE_GET_API(DictIteratorReseek); + REDISMODULE_GET_API(DictNextC); + REDISMODULE_GET_API(DictPrevC); + REDISMODULE_GET_API(DictNext); + REDISMODULE_GET_API(DictPrev); + REDISMODULE_GET_API(DictCompare); + REDISMODULE_GET_API(DictCompareC); #ifdef REDISMODULE_EXPERIMENTAL_API REDISMODULE_GET_API(GetThreadSafeContext); @@ -406,9 +530,33 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(IsBlockedReplyRequest); REDISMODULE_GET_API(IsBlockedTimeoutRequest); REDISMODULE_GET_API(GetBlockedClientPrivateData); + REDISMODULE_GET_API(GetBlockedClientHandle); REDISMODULE_GET_API(AbortBlock); + REDISMODULE_GET_API(SetDisconnectCallback); REDISMODULE_GET_API(SubscribeToKeyspaceEvents); - + REDISMODULE_GET_API(BlockedClientDisconnected); + REDISMODULE_GET_API(RegisterClusterMessageReceiver); + REDISMODULE_GET_API(SendClusterMessage); + REDISMODULE_GET_API(GetClusterNodeInfo); + REDISMODULE_GET_API(GetClusterNodesList); + REDISMODULE_GET_API(FreeClusterNodesList); + REDISMODULE_GET_API(CreateTimer); + REDISMODULE_GET_API(StopTimer); + REDISMODULE_GET_API(GetTimerInfo); + REDISMODULE_GET_API(GetMyClusterID); + REDISMODULE_GET_API(GetClusterSize); + REDISMODULE_GET_API(GetRandomBytes); + REDISMODULE_GET_API(GetRandomHexChars); + REDISMODULE_GET_API(SetClusterFlags); + REDISMODULE_GET_API(ExportSharedAPI); + REDISMODULE_GET_API(GetSharedAPI); + REDISMODULE_GET_API(RegisterCommandFilter); + REDISMODULE_GET_API(UnregisterCommandFilter); + REDISMODULE_GET_API(CommandFilterArgsCount); + REDISMODULE_GET_API(CommandFilterArgGet); + REDISMODULE_GET_API(CommandFilterArgInsert); + REDISMODULE_GET_API(CommandFilterArgReplace); + REDISMODULE_GET_API(CommandFilterArgDelete); #endif if (RedisModule_IsModuleNameBusy && RedisModule_IsModuleNameBusy(name)) return REDISMODULE_ERR; diff --git a/redismodule/run-tests.sh.in b/redismodule/run-tests.sh.in index 57a6843..194095d 100755 --- a/redismodule/run-tests.sh.in +++ b/redismodule/run-tests.sh.in @@ -1,6 +1,6 @@ #!/bin/sh -./redismodule_ut +valgrind --leak-check=full ./redismodule_ut if [ $? != 0 ] then exit -1 diff --git a/redismodule/src/exstrings.c b/redismodule/src/exstrings.c index 194edc5..c1fe8d1 100755 --- a/redismodule/src/exstrings.c +++ b/redismodule/src/exstrings.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nokia. + * Copyright (c) 2018-2020 Nokia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,26 +20,23 @@ */ #include "redismodule.h" -#include -#include -#include #include +#include #include -#include "../../redismodule/include/redismodule.h" #ifdef __UT__ #include "exstringsStub.h" +#include "commonStub.h" #endif + /* make sure the response is not NULL or an error. sends the error to the client and exit the current function if its */ #define ASSERT_NOERROR(r) \ if (r == NULL) { \ return RedisModule_ReplyWithError(ctx,"ERR reply is NULL"); \ } else if (RedisModule_CallReplyType(r) == REDISMODULE_REPLY_ERROR) { \ - RedisModule_ReplyWithCallReply(ctx,r); \ - RedisModule_FreeCallReply(r); \ - return REDISMODULE_ERR; \ + return RedisModule_ReplyWithCallReply(ctx,r); \ } #define OBJ_OP_NO 0 @@ -48,6 +45,28 @@ sends the error to the client and exit the current function if its */ #define OBJ_OP_IE (1<<4) /* OP if equal old value */ #define OBJ_OP_NE (1<<5) /* OP if not equal old value */ +#define DEF_COUNT 50 +#define ZERO 0 +#define MATCH_STR "MATCH" +#define COUNT_STR "COUNT" +#define SCANARGC 5 + +RedisModuleString *def_count_str = NULL, *match_str = NULL, *count_str = NULL, *zero_str = NULL; + +void InitStaticVariable() +{ + if (def_count_str == NULL) + def_count_str = RedisModule_CreateStringFromLongLong(NULL, DEF_COUNT); + if (match_str == NULL) + match_str = RedisModule_CreateString(NULL, MATCH_STR, sizeof(MATCH_STR)); + if (count_str == NULL) + count_str = RedisModule_CreateString(NULL, COUNT_STR, sizeof(COUNT_STR)); + if (zero_str == NULL) + zero_str = RedisModule_CreateStringFromLongLong(NULL, ZERO); + + return; +} + int getKeyType(RedisModuleCtx *ctx, RedisModuleString *key_str) { RedisModuleKey *key = RedisModule_OpenKey(ctx, key_str, REDISMODULE_READ); @@ -152,11 +171,13 @@ int setStringGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int SetIE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + RedisModule_AutoMemory(ctx); return setStringGenericCommand(ctx, argv, argc, OBJ_OP_IE); } int SetNE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + RedisModule_AutoMemory(ctx); return setStringGenericCommand(ctx, argv, argc, OBJ_OP_NE); } @@ -215,136 +236,22 @@ int delStringGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int DelIE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + RedisModule_AutoMemory(ctx); return delStringGenericCommand(ctx, argv, argc, OBJ_OP_IE); } int DelNE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + RedisModule_AutoMemory(ctx); return delStringGenericCommand(ctx, argv, argc, OBJ_OP_NE); } - -int NGet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) -{ - RedisModuleCallReply *reply = NULL; - - if (argc != 2) - return RedisModule_WrongArity(ctx); - - /* Call the command to get keys with pattern. */ - reply = RedisModule_Call(ctx, "KEYS", "s", argv[1]); - ASSERT_NOERROR(reply) - - /* Prepare the arguments for the command. */ - size_t items = RedisModule_CallReplyLength(reply); - if (items == 0) { - //RedisModule_ReplyWithArray(ctx, items); - RedisModule_ReplyWithCallReply(ctx, reply); - RedisModule_FreeCallReply(reply); - } - else { - RedisModuleString *cmdargv[items]; - size_t i=0, j; - for (j = 0; j < items; j++) { - RedisModuleString *rms = RedisModule_CreateStringFromCallReply(RedisModule_CallReplyArrayElement(reply, j)); - cmdargv[i++] = rms; - - /*Assume all keys via SDL is string type for sake of saving time*/ -#if 0 - /*Check if key type is string*/ - RedisModuleKey *key = RedisModule_OpenKey(ctx, rms ,REDISMODULE_READ); - - if (key) { - int type = RedisModule_KeyType(key); - RedisModule_CloseKey(key); - if (type == REDISMODULE_KEYTYPE_STRING) { - cmdargv[i++] = rms; - } - } else { - RedisModule_CloseKey(key); - } -#endif - } - RedisModule_FreeCallReply(reply); - - reply = RedisModule_Call(ctx, "MGET", "v", cmdargv, i); - ASSERT_NOERROR(reply) - items = RedisModule_CallReplyLength(reply); - RedisModule_ReplyWithArray(ctx, i*2); - for (j = 0; (jkey_val_pairs, setParamsPtr->length); ASSERT_NOERROR(setReply) - int replytype = RedisModule_CallReplyType(setReply); - if (replytype == REDISMODULE_REPLY_NULL) { - RedisModule_ReplyWithNull(ctx); - } else { - multiPubCommand(ctx, pubParamsPtr); - RedisModule_ReplyWithCallReply(ctx, setReply); - } + multiPubCommand(ctx, pubParamsPtr); + RedisModule_ReplyWithCallReply(ctx, setReply); RedisModule_FreeCallReply(setReply); return REDISMODULE_OK; } @@ -354,12 +261,13 @@ int SetPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) if (argc < 5 || (argc % 2) == 0) return RedisModule_WrongArity(ctx); + RedisModule_AutoMemory(ctx); SetParams setParams = { .key_val_pairs = argv + 1, .length = argc - 3 }; PubParams pubParams = { - .channel_msg_pairs = argv + argc - 2, + .channel_msg_pairs = argv + 1 + setParams.length, .length = 2 }; @@ -371,6 +279,7 @@ int SetMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc if (argc < 7 || (argc % 2) == 0) return RedisModule_WrongArity(ctx); + RedisModule_AutoMemory(ctx); long long setPairsCount, pubPairsCount; RedisModule_StringToLongLong(argv[1], &setPairsCount); RedisModule_StringToLongLong(argv[2], &pubPairsCount); @@ -380,6 +289,7 @@ int SetMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc long long setLen, pubLen; setLen = 2*setPairsCount; pubLen = 2*pubPairsCount; + if (setLen + pubLen + 3 != argc) return RedisModule_ReplyWithError(ctx, "ERR SET_PAIR_COUNT or PUB_PAIR_COUNT do not match the total pair count"); @@ -397,9 +307,6 @@ int SetMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc int setIENEPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag) { - if (argc < 6 || (argc % 2) != 0) - return RedisModule_WrongArity(ctx); - SetParams setParams = { .key_val_pairs = argv + 1, .length = 2 @@ -430,21 +337,35 @@ int setIENEPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int ar return setPubStringCommon(ctx, &setParams, &pubParams); } -int SetNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) +int SetIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - return setIENEPubStringCommon(ctx, argv, argc, OBJ_OP_NE); + if (argc != 6) + return RedisModule_WrongArity(ctx); + + RedisModule_AutoMemory(ctx); + return setIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE); } -int SetIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) +int SetIEMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + if (argc < 6 || (argc % 2) != 0) + return RedisModule_WrongArity(ctx); + + RedisModule_AutoMemory(ctx); return setIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE); } -int setXXNXPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag) +int SetNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc < 5 || (argc % 2) == 0) + if (argc != 6) return RedisModule_WrongArity(ctx); + RedisModule_AutoMemory(ctx); + return setIENEPubStringCommon(ctx, argv, argc, OBJ_OP_NE); +} + +int setXXNXPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag) +{ SetParams setParams = { .key_val_pairs = argv + 1, .length = 2 @@ -469,11 +390,28 @@ int setXXNXPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int ar int SetNXPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + if (argc != 5) + return RedisModule_WrongArity(ctx); + + RedisModule_AutoMemory(ctx); + return setXXNXPubStringCommon(ctx, argv, argc, OBJ_OP_NX); +} + +int SetNXMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) +{ + if (argc < 5 || (argc % 2) == 0) + return RedisModule_WrongArity(ctx); + + RedisModule_AutoMemory(ctx); return setXXNXPubStringCommon(ctx, argv, argc, OBJ_OP_NX); } int SetXXPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + if (argc != 5) + return RedisModule_WrongArity(ctx); + + RedisModule_AutoMemory(ctx); return setXXNXPubStringCommon(ctx, argv, argc, OBJ_OP_XX); } @@ -499,6 +437,7 @@ int DelPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) if (argc < 4) return RedisModule_WrongArity(ctx); + RedisModule_AutoMemory(ctx); DelParams delParams = { .keys = argv + 1, .length = argc - 3 @@ -516,6 +455,7 @@ int DelMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc if (argc < 6) return RedisModule_WrongArity(ctx); + RedisModule_AutoMemory(ctx); long long delCount, pubPairsCount; RedisModule_StringToLongLong(argv[1], &delCount); RedisModule_StringToLongLong(argv[2], &pubPairsCount); @@ -542,9 +482,6 @@ int DelMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc int delIENEPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag) { - if (argc < 5 || (argc % 2) == 0) - return RedisModule_WrongArity(ctx); - DelParams delParams = { .keys = argv + 1, .length = 1 @@ -577,12 +514,29 @@ int delIENEPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int ar int DelIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE); + if (argc != 5) + return RedisModule_WrongArity(ctx); + + RedisModule_AutoMemory(ctx); + return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE); +} + +int DelIEMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) +{ + if (argc < 5 || (argc % 2) == 0) + return RedisModule_WrongArity(ctx); + + RedisModule_AutoMemory(ctx); + return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE); } int DelNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_NE); + if (argc != 5) + return RedisModule_WrongArity(ctx); + + RedisModule_AutoMemory(ctx); + return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_NE); } /* This function must be present on each Redis module. It is used in order to @@ -610,14 +564,6 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) DelNE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; - if (RedisModule_CreateCommand(ctx,"nget", - NGet_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"ndel", - NDel_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - if (RedisModule_CreateCommand(ctx,"msetpub", SetPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; @@ -630,6 +576,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) SetIEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; + if (RedisModule_CreateCommand(ctx,"setiempub", + SetIEMPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) + return REDISMODULE_ERR; + if (RedisModule_CreateCommand(ctx,"setnepub", SetNEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; @@ -642,6 +592,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) SetNXPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; + if (RedisModule_CreateCommand(ctx,"setnxmpub", + SetNXMPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) + return REDISMODULE_ERR; + if (RedisModule_CreateCommand(ctx,"delpub", DelPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; @@ -654,6 +608,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) DelIEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; + if (RedisModule_CreateCommand(ctx,"deliempub", + DelIEMPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) + return REDISMODULE_ERR; + if (RedisModule_CreateCommand(ctx,"delnepub", DelNEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; diff --git a/redismodule/tst/mock/include/commonStub.h b/redismodule/tst/mock/include/commonStub.h new file mode 100644 index 0000000..dc87fa7 --- /dev/null +++ b/redismodule/tst/mock/include/commonStub.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018-2020 Nokia. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This source code is part of the near-RT RIC (RAN Intelligent Controller) + * platform project (RICP). + */ + +#ifndef COMMONSTUB_H_ +#define COMMONSTUB_H_ + + +#include + +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg); + + +#endif diff --git a/redismodule/tst/mock/include/exstringsStub.h b/redismodule/tst/mock/include/exstringsStub.h index 572f64c..756e5de 100755 --- a/redismodule/tst/mock/include/exstringsStub.h +++ b/redismodule/tst/mock/include/exstringsStub.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nokia. + * Copyright (c) 2018-2020 Nokia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,6 @@ #include #include #include -#include "../../../../redismodule/tst/mock/include/redismodule.h" int setStringGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, const int flag); int SetIE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); @@ -40,15 +39,15 @@ int DelNE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); int SetPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); int SetMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); int SetIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); +int SetIEMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); int SetNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); int SetNXPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); +int SetNXMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); int SetXXPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); int DelPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); int DelMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); int DelIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); +int DelIEMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); int DelNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); -int NGet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); -int NDel_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); - #endif diff --git a/redismodule/tst/mock/include/redismodule.h b/redismodule/tst/mock/include/redismodule.h index 3e9b93b..414bdc7 100755 --- a/redismodule/tst/mock/include/redismodule.h +++ b/redismodule/tst/mock/include/redismodule.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nokia. + * Copyright (c) 2018-2020 Nokia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,11 +26,6 @@ #include #include -/* ---------------- Defines common between core and modules --------------- */ - - - - /* Error status return values. */ #define REDISMODULE_OK 0 #define REDISMODULE_ERR 1 @@ -42,9 +37,6 @@ #define REDISMODULE_READ (1<<0) #define REDISMODULE_WRITE (1<<1) -#define REDISMODULE_LIST_HEAD 0 -#define REDISMODULE_LIST_TAIL 1 - /* Key types. */ #define REDISMODULE_KEYTYPE_EMPTY 0 #define REDISMODULE_KEYTYPE_STRING 1 @@ -65,81 +57,22 @@ /* Postponed array length. */ #define REDISMODULE_POSTPONED_ARRAY_LEN -1 -/* Expire */ -#define REDISMODULE_NO_EXPIRE -1 - -/* Sorted set API flags. */ -#define REDISMODULE_ZADD_XX (1<<0) -#define REDISMODULE_ZADD_NX (1<<1) -#define REDISMODULE_ZADD_ADDED (1<<2) -#define REDISMODULE_ZADD_UPDATED (1<<3) -#define REDISMODULE_ZADD_NOP (1<<4) - -/* Hash API flags. */ -#define REDISMODULE_HASH_NONE 0 -#define REDISMODULE_HASH_NX (1<<0) -#define REDISMODULE_HASH_XX (1<<1) -#define REDISMODULE_HASH_CFIELDS (1<<2) -#define REDISMODULE_HASH_EXISTS (1<<3) - -/* Context Flags: Info about the current context returned by RM_GetContextFlags */ - -/* The command is running in the context of a Lua script */ -#define REDISMODULE_CTX_FLAGS_LUA 0x0001 -/* The command is running inside a Redis transaction */ -#define REDISMODULE_CTX_FLAGS_MULTI 0x0002 -/* The instance is a master */ -#define REDISMODULE_CTX_FLAGS_MASTER 0x0004 -/* The instance is a slave */ -#define REDISMODULE_CTX_FLAGS_SLAVE 0x0008 -/* The instance is read-only (usually meaning it's a slave as well) */ -#define REDISMODULE_CTX_FLAGS_READONLY 0x0010 -/* The instance is running in cluster mode */ -#define REDISMODULE_CTX_FLAGS_CLUSTER 0x0020 -/* The instance has AOF enabled */ -#define REDISMODULE_CTX_FLAGS_AOF 0x0040 // -/* The instance has RDB enabled */ -#define REDISMODULE_CTX_FLAGS_RDB 0x0080 // -/* The instance has Maxmemory set */ -#define REDISMODULE_CTX_FLAGS_MAXMEMORY 0x0100 -/* Maxmemory is set and has an eviction policy that may delete keys */ -#define REDISMODULE_CTX_FLAGS_EVICT 0x0200 - - -/* A special pointer that we can use between the core and the module to signal - * field deletion, and that is impossible to be a valid pointer. */ -#define REDISMODULE_HASH_DELETE ((RedisModuleString*)(long)1) - /* Error messages. */ #define REDISMODULE_ERRORMSG_WRONGTYPE "WRONGTYPE Operation against a key holding the wrong kind of value" -#define REDISMODULE_POSITIVE_INFINITE (1.0/0.0) -#define REDISMODULE_NEGATIVE_INFINITE (-1.0/0.0) - #define REDISMODULE_NOT_USED(V) ((void) V) -/* ------------------------- End of common defines ------------------------ */ - - - - -#ifndef REDISMODULE_CORE - - - typedef long long mstime_t; -/* Incomplete structures for compiler checks but opaque access. */ -typedef struct RedisModuleCtx RedisModuleCtx; -typedef struct RedisModuleKey RedisModuleKey; -typedef struct RedisModuleString RedisModuleString; -typedef struct RedisModuleCallReply RedisModuleCallReply; -typedef struct RedisModuleIO RedisModuleIO; -typedef struct RedisModuleType RedisModuleType; -typedef struct RedisModuleDigest RedisModuleDigest; -typedef struct RedisModuleBlockedClient RedisModuleBlockedClient; - -//typedef int (*RedisModuleCmdFunc) (RedisModuleCtx *ctx, RedisModuleString **argv, int argc); +/* UT dummy definitions for opaque redis types */ +typedef struct { int dummy; } RedisModuleCtx; +typedef struct { int dummy; } RedisModuleKey; +typedef struct { int dummy; } RedisModuleString; +typedef struct { int dummy; } RedisModuleCallReply; +typedef struct { int dummy; } RedisModuleIO; +typedef struct { int dummy; } RedisModuleType; +typedef struct { int dummy; } RedisModuleDigest; +typedef struct { int dummy; } RedisModuleBlockedClient; typedef void *(*RedisModuleTypeLoadFunc)(RedisModuleIO *rdb, int encver); typedef void (*RedisModuleTypeSaveFunc)(RedisModuleIO *rdb, void *value); @@ -148,209 +81,8 @@ typedef size_t (*RedisModuleTypeMemUsageFunc)(const void *value); typedef void (*RedisModuleTypeDigestFunc)(RedisModuleDigest *digest, void *value); typedef void (*RedisModuleTypeFreeFunc)(void *value); -#define REDISMODULE_TYPE_METHOD_VERSION 1 -typedef struct RedisModuleTypeMethods { - uint64_t version; - RedisModuleTypeLoadFunc rdb_load; - RedisModuleTypeSaveFunc rdb_save; - RedisModuleTypeRewriteFunc aof_rewrite; - RedisModuleTypeMemUsageFunc mem_usage; - RedisModuleTypeDigestFunc digest; - RedisModuleTypeFreeFunc free; -} RedisModuleTypeMethods; - -#define REDISMODULE_GET_API(name) \ - RedisModule_GetApi("RedisModule_" #name, ((void **)&RedisModule_ ## name)) - -#define REDISMODULE_API_FUNC(x) (*x) - -#if 1 - - -typedef struct redisObject { - unsigned type:4; - unsigned encoding:4; - int refcount; - void *ptr; -} robj; -/* This structure represents a module inside the system. */ -struct RedisModule { - void *handle; /* Module dlopen() handle. */ - char *name; /* Module name. */ - int ver; /* Module version. We use just progressive integers. */ - int apiver; /* Module API version as requested during initialization.*/ - //list *types; /* Module data types. */ -}; -typedef struct RedisModule RedisModule; - -//static dict *modules; /* Hash table of modules. SDS -> RedisModule ptr.*/ - -/* Entries in the context->amqueue array, representing objects to free - * when the callback returns. */ -struct AutoMemEntry { - void *ptr; - int type; -}; - -/* AutMemEntry type field values. */ -#define REDISMODULE_AM_KEY 0 -#define REDISMODULE_AM_STRING 1 -#define REDISMODULE_AM_REPLY 2 -#define REDISMODULE_AM_FREED 3 /* Explicitly freed by user already. */ - -/* The pool allocator block. Redis Modules can allocate memory via this special - * allocator that will automatically release it all once the callback returns. - * This means that it can only be used for ephemeral allocations. However - * there are two advantages for modules to use this API: - * - * 1) The memory is automatically released when the callback returns. - * 2) This allocator is faster for many small allocations since whole blocks - * are allocated, and small pieces returned to the caller just advancing - * the index of the allocation. - * - * Allocations are always rounded to the size of the void pointer in order - * to always return aligned memory chunks. */ - -#define REDISMODULE_POOL_ALLOC_MIN_SIZE (1024*8) -#define REDISMODULE_POOL_ALLOC_ALIGN (sizeof(void*)) - -typedef struct RedisModulePoolAllocBlock { - uint32_t size; - uint32_t used; - struct RedisModulePoolAllocBlock *next; - char memory[]; -} RedisModulePoolAllocBlock; - -/* This structure represents the context in which Redis modules operate. - * Most APIs module can access, get a pointer to the context, so that the API - * implementation can hold state across calls, or remember what to free after - * the call and so forth. - * - * Note that not all the context structure is always filled with actual values - * but only the fields needed in a given context. */ - -struct RedisModuleBlockedClient; - -struct RedisModuleCtx { - void *getapifuncptr; /* NOTE: Must be the first field. */ - struct RedisModule *module; /* Module reference. */ - //client *client; /* Client calling a command. */ - struct RedisModuleBlockedClient *blocked_client; /* Blocked client for - thread safe context. */ - struct AutoMemEntry *amqueue; /* Auto memory queue of objects to free. */ - int amqueue_len; /* Number of slots in amqueue. */ - int amqueue_used; /* Number of used slots in amqueue. */ - int flags; /* REDISMODULE_CTX_... flags. */ - void **postponed_arrays; /* To set with RM_ReplySetArrayLength(). */ - int postponed_arrays_count; /* Number of entries in postponed_arrays. */ - void *blocked_privdata; /* Privdata set when unblocking a client. */ - - /* Used if there is the REDISMODULE_CTX_KEYS_POS_REQUEST flag set. */ - int *keys_pos; - int keys_count; - - struct RedisModulePoolAllocBlock *pa_head; -}; -typedef struct RedisModuleCtx RedisModuleCtx; - -#define REDISMODULE_CTX_INIT {(void*)(unsigned long)&RM_GetApi, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0, NULL, NULL, 0, NULL} -#define REDISMODULE_CTX_MULTI_EMITTED (1<<0) -#define REDISMODULE_CTX_AUTO_MEMORY (1<<1) -#define REDISMODULE_CTX_KEYS_POS_REQUEST (1<<2) -#define REDISMODULE_CTX_BLOCKED_REPLY (1<<3) -#define REDISMODULE_CTX_BLOCKED_TIMEOUT (1<<4) -#define REDISMODULE_CTX_THREAD_SAFE (1<<5) - -/* This represents a Redis key opened with RM_OpenKey(). */ -struct RedisModuleKey { - RedisModuleCtx *ctx; - //redisDb *db; - robj *key; /* Key name object. */ - robj *value; /* Value object, or NULL if the key was not found. */ - void *iter; /* Iterator. */ - int mode; /* Opening mode. */ - - /* Zset iterator. */ - uint32_t ztype; /* REDISMODULE_ZSET_RANGE_* */ - //zrangespec zrs; /* Score range. */ - //zlexrangespec zlrs; /* Lex range. */ - uint32_t zstart; /* Start pos for positional ranges. */ - uint32_t zend; /* End pos for positional ranges. */ - void *zcurrent; /* Zset iterator current node. */ - int zer; /* Zset iterator end reached flag - (true if end was reached). */ -}; -typedef struct RedisModuleKey RedisModuleKey; - -/* RedisModuleKey 'ztype' values. */ -#define REDISMODULE_ZSET_RANGE_NONE 0 /* This must always be 0. */ -#define REDISMODULE_ZSET_RANGE_LEX 1 -#define REDISMODULE_ZSET_RANGE_SCORE 2 -#define REDISMODULE_ZSET_RANGE_POS 3 - -/* Function pointer type of a function representing a command inside - * a Redis module. */ - typedef int (*RedisModuleCmdFunc) (RedisModuleCtx *ctx, RedisModuleString **argv, int argc); - -/* This struct holds the information about a command registered by a module.*/ -struct RedisModuleCommandProxy { - struct RedisModule *module; - RedisModuleCmdFunc func; - struct redisCommand *rediscmd; -}; -typedef struct RedisModuleCommandProxy RedisModuleCommandProxy; - -#define REDISMODULE_REPLYFLAG_NONE 0 -#define REDISMODULE_REPLYFLAG_TOPARSE (1<<0) /* Protocol must be parsed. */ -#define REDISMODULE_REPLYFLAG_NESTED (1<<1) /* Nested reply object. No proto - or struct free. */ - -/* Reply of RM_Call() function. The function is filled in a lazy - * way depending on the function called on the reply structure. By default - * only the type, proto and protolen are filled. */ -typedef struct RedisModuleCallReply { - RedisModuleCtx *ctx; - int type; /* REDISMODULE_REPLY_... */ - int flags; /* REDISMODULE_REPLYFLAG_... */ - size_t len; /* Len of strings or num of elements of arrays. */ - char *proto; /* Raw reply protocol. An SDS string at top-level object. */ - size_t protolen;/* Length of protocol. */ - union { - const char *str; /* String pointer for string and error replies. This - does not need to be freed, always points inside - a reply->proto buffer of the reply object or, in - case of array elements, of parent reply objects. */ - long long ll; /* Reply value for integer reply. */ - struct RedisModuleCallReply *array; /* Array of sub-reply elements. */ - } val; -} RedisModuleCallReply; - -/* Structure representing a blocked client. We get a pointer to such - * an object when blocking from modules. */ -typedef struct RedisModuleBlockedClient { - //client *client; /* Pointer to the blocked client. or NULL if the client - // was destroyed during the life of this object. */ - RedisModule *module; /* Module blocking the client. */ - RedisModuleCmdFunc reply_callback; /* Reply callback on normal completion.*/ - RedisModuleCmdFunc timeout_callback; /* Reply callback on timeout. */ - void (*free_privdata)(void *); /* privdata cleanup callback. */ - void *privdata; /* Module private data that may be used by the reply - or timeout callback. It is set via the - RedisModule_UnblockClient() API. */ - //client *reply_client; /* Fake client used to accumulate replies - // in thread safe contexts. */ - int dbid; /* Database number selected by the original client. */ -} RedisModuleBlockedClient; - -#define RedisModuleString robj - -#endif - - - - int RedisModule_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep); int RedisModule_WrongArity(RedisModuleCtx *ctx); int RedisModule_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll); @@ -366,27 +98,29 @@ int RedisModule_ReplyWithNull(RedisModuleCtx *ctx); int RedisModule_ReplyWithCallReply(RedisModuleCtx *ctx, RedisModuleCallReply *reply); const char *RedisModule_CallReplyStringPtr(RedisModuleCallReply *reply, size_t *len); RedisModuleString *RedisModule_CreateStringFromCallReply(RedisModuleCallReply *reply); -int RedisModule_StringToLongLong(const RedisModuleString *str, long long *ll); int RedisModule_KeyType(RedisModuleKey *kp); void RedisModule_CloseKey(RedisModuleKey *kp); -/* This is included inline inside each Redis module. */ int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver); size_t RedisModule_CallReplyLength(RedisModuleCallReply *reply); RedisModuleCallReply *RedisModule_CallReplyArrayElement(RedisModuleCallReply *reply, size_t idx); int RedisModule_ReplyWithArray(RedisModuleCtx *ctx, long len); - - -/* Things only defined for the modules core, not exported to modules - * including this file. */ - -#else - -/* Things only defined for the modules core, not exported to modules - * including this file. */ -#define RedisModuleString robj - -#endif /* REDISMODULE_CORE */ -#endif /* REDISMOUDLE_H */ +void RedisModule_FreeString(RedisModuleCtx *ctx, RedisModuleString *str); +RedisModuleBlockedClient *RedisModule_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms); +int RedisModule_UnblockClient(RedisModuleBlockedClient *bc, void *privdata); +int RedisModule_AbortBlock(RedisModuleBlockedClient *bc); +RedisModuleString *RedisModule_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t len); +void RedisModule_FreeThreadSafeContext(RedisModuleCtx *ctx); +int RedisModule_StringToLongLong(const RedisModuleString *str, long long *ll); +void RedisModule_ThreadSafeContextLock(RedisModuleCtx *ctx); +void RedisModule_ThreadSafeContextUnlock(RedisModuleCtx *ctx); +void RedisModule_ReplySetArrayLength(RedisModuleCtx *ctx, long len); +RedisModuleCtx *RedisModule_GetThreadSafeContext(RedisModuleBlockedClient *bc); +RedisModuleString *RedisModule_CreateStringFromLongLong(RedisModuleCtx *ctx, long long ll); +void RedisModule_AutoMemory(RedisModuleCtx *ctx); +void *RedisModule_Alloc(size_t bytes); +void RedisModule_Free(void *ptr); + +#endif /* REDISMODULE_H */ diff --git a/redismodule/tst/mock/src/commonStub.cpp b/redismodule/tst/mock/src/commonStub.cpp new file mode 100644 index 0000000..2df1df9 --- /dev/null +++ b/redismodule/tst/mock/src/commonStub.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018-2020 Nokia. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This source code is part of the near-RT RIC (RAN Intelligent Controller) + * platform project (RICP). + */ + + +#include +#include + +extern "C" { +#include +#include +#include + +#include "redismodule.h" +#include "commonStub.h" +} + +#include +#include +#include + +typedef struct RedisModuleBlockedClientArgs { + RedisModuleBlockedClient *bc; + RedisModuleString **argv; + int argc; +} RedisModuleBlockedClientArgs; + +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg) +{ + (void)thread; + (void)attr; + (void)start_routine; + if (mock().getData("pthread_create_free_block_client_args").getIntValue()) { + RedisModuleBlockedClientArgs* bca = (RedisModuleBlockedClientArgs*)arg; + free(bca->bc); + free(bca); + } + + return mock() + .actualCall("pthread_create") + .returnIntValueOrDefault(0); +} diff --git a/redismodule/tst/mock/src/redismoduleStub.cpp b/redismodule/tst/mock/src/redismoduleStub.cpp index 029c48b..bfcdb22 100755 --- a/redismodule/tst/mock/src/redismoduleStub.cpp +++ b/redismodule/tst/mock/src/redismoduleStub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nokia. + * Copyright (c) 2018-2020 Nokia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,14 +20,9 @@ */ -#include -#include #include #include - - - extern "C" { #include "redismodule.h" #include @@ -35,6 +30,9 @@ extern "C" { #include } +#include +#include + int RedisModule_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep) { @@ -52,6 +50,7 @@ int RedisModule_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModule int RedisModule_WrongArity(RedisModuleCtx *ctx) { (void)ctx; + mock().setData("RedisModule_WrongArity", 1); return REDISMODULE_ERR; } @@ -105,6 +104,8 @@ RedisModuleCallReply *RedisModule_Call(RedisModuleCtx *ctx, const char *cmdname, mock().setData("KEYS", 1); else if (!strcmp(cmdname, "MGET")) mock().setData("MGET", 1); + else if (!strcmp(cmdname, "SCAN")) + mock().setData("SCAN", 1); if (mock().hasData("RedisModule_Call_Return_Null")) return NULL; @@ -157,7 +158,7 @@ const char *RedisModule_StringPtrLen(const RedisModuleString *str, size_t *len) { (void)str; - *len = 5; + if (len) *len = 5; if (mock().hasData("RedisModule_String_same")) { return "11111"; @@ -168,6 +169,17 @@ const char *RedisModule_StringPtrLen(const RedisModuleString *str, size_t *len) return "22222"; } + if (mock().hasData("RedisModule_String_count")) + { + return "COUNT"; + } + + if (mock().hasData("RedisModule_String_count1")) + { + if (len) *len = 6; + return "COUNT1"; + } + return "11111"; } @@ -207,17 +219,17 @@ const char *RedisModule_CallReplyStringPtr(RedisModuleCallReply *reply, size_t * { (void)reply; - *len = 5; - if (mock().hasData("RedisModule_String_same")) { + if (len) + *len = 5; return "11111"; } - if (mock().hasData("RedisModule_String_nosame")) { - *len = 6; + if (len) + *len = 6; return "333333"; } @@ -294,9 +306,62 @@ int RedisModule_ReplyWithArray(RedisModuleCtx *ctx, long len) return REDISMODULE_OK; } +void RedisModule_FreeString(RedisModuleCtx *ctx, RedisModuleString *str) +{ + (void)ctx; + (void)str; + mock().setData("RedisModule_FreeString", mock().getData("RedisModule_FreeString").getIntValue()+1); + return; +} + +RedisModuleBlockedClient *RedisModule_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms) +{ + (void)ctx; + (void)reply_callback; + (void)timeout_callback; + (void)free_privdata; + (void)timeout_ms; + RedisModuleBlockedClient *bc = (RedisModuleBlockedClient*)malloc(sizeof(RedisModuleBlockedClient)); + mock().setData("RedisModule_BlockClient", 1); + return bc; +} + +int RedisModule_UnblockClient(RedisModuleBlockedClient *bc, void *privdata) +{ + (void)privdata; + free(bc); + mock().setData("RedisModule_UnblockClient", mock().getData("RedisModule_UnblockClient").getIntValue()+1); + return REDISMODULE_OK; +} + +int RedisModule_AbortBlock(RedisModuleBlockedClient *bc) +{ + free(bc); + mock().setData("RedisModule_AbortBlock", 1); + return REDISMODULE_OK; +} + +RedisModuleString *RedisModule_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t len) +{ + (void)ctx; + (void)ptr; + (void)len; + RedisModuleString *rms = (RedisModuleString*)malloc(sizeof(RedisModuleString)); + mock().setData("RedisModule_CreateString", mock().getData("RedisModule_CreateString").getIntValue()+1); + return rms; +} + +void RedisModule_FreeThreadSafeContext(RedisModuleCtx *ctx) +{ + (void)ctx; + mock().setData("RedisModule_FreeThreadSafeContext", 1); + return; +} + int RedisModule_StringToLongLong(const RedisModuleString *str, long long *ll) { - (void) str; + (void)str; + int call_no = mock().getData("RedisModule_StringToLongLongCallCount").getIntValue(); switch(call_no) { case 0: @@ -311,3 +376,62 @@ int RedisModule_StringToLongLong(const RedisModuleString *str, long long *ll) mock().setData("RedisModule_StringToLongLongCallCount", call_no + 1); return REDISMODULE_OK; } + +void RedisModule_ThreadSafeContextLock(RedisModuleCtx *ctx) +{ + (void)ctx; + mock().setData("RedisModule_ThreadSafeContextLock", 1); + return; +} + +void RedisModule_ThreadSafeContextUnlock(RedisModuleCtx *ctx) +{ + (void)ctx; + mock().setData("RedisModule_ThreadSafeContextUnlock", 1); + return; +} + +void RedisModule_ReplySetArrayLength(RedisModuleCtx *ctx, long len) +{ + (void)ctx; + mock().setData("RedisModule_ReplySetArrayLength", (int)len); + return; +} + +RedisModuleCtx *RedisModule_GetThreadSafeContext(RedisModuleBlockedClient *bc) +{ + (void) bc; + mock().setData("RedisModule_GetThreadSafeContext", 1); + return NULL; +} + +RedisModuleString *RedisModule_CreateStringFromLongLong(RedisModuleCtx *ctx, long long ll) +{ + (void)ctx; + (void)ll; + RedisModuleString *rms = (RedisModuleString*)malloc(sizeof(RedisModuleString)); + mock().setData("RedisModule_CreateStringFromLongLong", mock().getData("RedisModule_CreateStringFromLongLong").getIntValue()+1); + return rms; +} + +void RedisModule_AutoMemory(RedisModuleCtx *ctx) +{ + (void)ctx; + int old = mock().getData("RedisModule_AutoMemory").getIntValue(); + mock().setData("RedisModule_AutoMemory", old + 1); + return; +} + +void *RedisModule_Alloc(size_t bytes) +{ + mock() + .actualCall("RedisModule_Alloc"); + return malloc(bytes); +} + +void RedisModule_Free(void *ptr) +{ + mock() + .actualCall("RedisModule_Free"); + free(ptr); +} diff --git a/redismodule/tst/src/exstrings_test.cpp b/redismodule/tst/src/exstrings_test.cpp index 4816de5..d239eea 100755 --- a/redismodule/tst/src/exstrings_test.cpp +++ b/redismodule/tst/src/exstrings_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nokia. + * Copyright (c) 2018-2020 Nokia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,18 +19,6 @@ * platform project (RICP). */ -#include -#include -#include -#include -#include -#include - - -//#include -//#include -//#include - extern "C" { #include "exstringsStub.h" @@ -46,6 +34,11 @@ extern "C" { #define OBJ_OP_IE (1<<4) /* OP if equal old value */ #define OBJ_OP_NE (1<<5) /* OP if not equal old value */ +typedef struct RedisModuleBlockedClientArgs { + RedisModuleBlockedClient *bc; + RedisModuleString **argv; + int argc; +} RedisModuleBlockedClientArgs; TEST_GROUP(exstring) { @@ -88,6 +81,7 @@ TEST(exstring, setie) int ret = SetIE_RedisCommand(&ctx, redisStrVec, 4); CHECK_EQUAL(ret, 0); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; } @@ -106,6 +100,7 @@ TEST(exstring, setne) mock().setData("RedisModule_String_same", 1); int ret = SetNE_RedisCommand(&ctx,redisStrVec, 4); CHECK_EQUAL(ret, 0); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; } @@ -266,6 +261,7 @@ TEST(exstring, delie) int ret = DelIE_RedisCommand(&ctx, redisStrVec, 3); CHECK_EQUAL(ret, 0); mock().checkExpectations(); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; } @@ -285,6 +281,7 @@ TEST(exstring, delne) int ret = DelNE_RedisCommand(&ctx,redisStrVec, 3); CHECK_EQUAL(ret, 0); mock().checkExpectations(); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; } @@ -446,144 +443,6 @@ TEST(exstring, delne_command_key_string_nosame_reply) } -TEST(exstring, setpub) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[5]); - - redisStrVec[0] = (RedisModuleString *)1; - redisStrVec[1] = (RedisModuleString *)1; - redisStrVec[2] = (RedisModuleString *)1; - redisStrVec[3] = (RedisModuleString *)1; - redisStrVec[4] = (RedisModuleString *)1; - - mock().setData("RedisModule_OpenKey_have", 1); - mock().setData("RedisModule_KeyType_str", 1); - mock().setData("RedisModule_String_same", 1); - mock().setData("RedisModule_CallReplyType_null", 1); - - int ret = SetPub_RedisCommand(&ctx, redisStrVec, 5); - CHECK_EQUAL(ret, REDISMODULE_OK); - mock().checkExpectations(); - delete []redisStrVec; -} - -TEST(exstring, setmpub) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[11]); - - for (int i = 0 ; i < 11 ; ++i) - redisStrVec[i] = (RedisModuleString *)1; - - mock().setData("RedisModule_OpenKey_have", 1); - mock().setData("RedisModule_KeyType_str", 1); - mock().setData("RedisModule_String_same", 1); - mock().setData("RedisModule_CallReplyType_null", 1); - mock().setData("RedisModule_StringToLongLongCallCount", 0); - mock().setData("RedisModule_StringToLongLongCall_1", 2); - mock().setData("RedisModule_StringToLongLongCall_2", 2); - - int ret = SetMPub_RedisCommand(&ctx, redisStrVec, 11); - CHECK_EQUAL(ret, REDISMODULE_OK); - mock().checkExpectations(); - delete []redisStrVec; -} - -TEST(exstring, setxxpub) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[5]); - - redisStrVec[0] = (RedisModuleString *)1; - redisStrVec[1] = (RedisModuleString *)1; - redisStrVec[2] = (RedisModuleString *)1; - redisStrVec[3] = (RedisModuleString *)1; - redisStrVec[4] = (RedisModuleString *)1; - - mock().setData("RedisModule_OpenKey_have", 1); - mock().setData("RedisModule_KeyType_str", 1); - mock().setData("RedisModule_String_same", 1); - mock().setData("RedisModule_CallReplyType_null", 1); - - mock().expectOneCall("RedisModule_CloseKey"); - int ret = SetXXPub_RedisCommand(&ctx, redisStrVec, 5); - CHECK_EQUAL(ret, REDISMODULE_OK); - mock().checkExpectations(); - delete []redisStrVec; -} - -TEST(exstring, setnxpub) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[5]); - - redisStrVec[0] = (RedisModuleString *)1; - redisStrVec[1] = (RedisModuleString *)1; - redisStrVec[2] = (RedisModuleString *)1; - redisStrVec[3] = (RedisModuleString *)1; - redisStrVec[4] = (RedisModuleString *)1; - - mock().setData("RedisModule_OpenKey_have", 1); - mock().setData("RedisModule_KeyType_str", 1); - mock().setData("RedisModule_String_same", 1); - mock().setData("RedisModule_CallReplyType_null", 1); - - mock().expectOneCall("RedisModule_CloseKey"); - int ret = SetNXPub_RedisCommand(&ctx, redisStrVec, 5); - CHECK_EQUAL(ret, REDISMODULE_OK); - mock().checkExpectations(); - delete []redisStrVec; -} - -TEST(exstring, setiepub) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[6]); - - redisStrVec[0] = (RedisModuleString *)1; - redisStrVec[1] = (RedisModuleString *)1; - redisStrVec[2] = (RedisModuleString *)1; - redisStrVec[3] = (RedisModuleString *)1; - redisStrVec[4] = (RedisModuleString *)1; - redisStrVec[5] = (RedisModuleString *)1; - - mock().setData("RedisModule_OpenKey_have", 1); - mock().setData("RedisModule_KeyType_str", 1); - mock().setData("RedisModule_String_same", 1); - mock().setData("RedisModule_CallReplyType_null", 1); - - mock().expectOneCall("RedisModule_CloseKey"); - int ret = SetIEPub_RedisCommand(&ctx, redisStrVec, 6); - CHECK_EQUAL(ret, REDISMODULE_OK); - mock().checkExpectations(); - delete []redisStrVec; -} - -TEST(exstring, setnepub) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[6]); - - redisStrVec[0] = (RedisModuleString *)1; - redisStrVec[1] = (RedisModuleString *)1; - redisStrVec[2] = (RedisModuleString *)1; - redisStrVec[3] = (RedisModuleString *)1; - redisStrVec[4] = (RedisModuleString *)1; - redisStrVec[5] = (RedisModuleString *)1; - - mock().setData("RedisModule_OpenKey_have", 1); - mock().setData("RedisModule_KeyType_str", 1); - mock().setData("RedisModule_String_same", 1); - mock().setData("RedisModule_CallReplyType_null", 1); - - mock().expectOneCall("RedisModule_CloseKey"); - int ret = SetNEPub_RedisCommand(&ctx, redisStrVec, 6); - CHECK_EQUAL(ret, REDISMODULE_OK); - mock().checkExpectations(); - delete []redisStrVec; -} - TEST(exstring, setpub_command_parameter_number_incorrect) { RedisModuleCtx ctx; @@ -616,6 +475,10 @@ TEST(exstring, setpub_command_parameter_number_incorrect) ret = SetNXPub_RedisCommand(&ctx, 0, 3); CHECK_EQUAL(ret, REDISMODULE_ERR); + ret = 0; + ret = SetNXMPub_RedisCommand(&ctx, 0, 3); + CHECK_EQUAL(ret, REDISMODULE_ERR); + ret = 0; ret = SetNXPub_RedisCommand(&ctx, 0, 6); CHECK_EQUAL(ret, REDISMODULE_ERR); @@ -624,6 +487,10 @@ TEST(exstring, setpub_command_parameter_number_incorrect) ret = SetIEPub_RedisCommand(&ctx, 0, 4); CHECK_EQUAL(ret, REDISMODULE_ERR); + ret = 0; + ret = SetIEMPub_RedisCommand(&ctx, 0, 4); + CHECK_EQUAL(ret, REDISMODULE_ERR); + ret = 0; ret = SetIEPub_RedisCommand(&ctx, 0, 9); CHECK_EQUAL(ret, REDISMODULE_ERR); @@ -637,32 +504,6 @@ TEST(exstring, setpub_command_parameter_number_incorrect) CHECK_EQUAL(ret, REDISMODULE_ERR); } -TEST(exstring, setpub_command_no_key_replynull) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[5]); - - redisStrVec[0] = (RedisModuleString *)0; - redisStrVec[1] = (RedisModuleString *)1; - redisStrVec[2] = (RedisModuleString *)2; - redisStrVec[3] = (RedisModuleString *)3; - redisStrVec[4] = (RedisModuleString *)4; - - mock().setData("RedisModule_KeyType_empty", 1); - mock().setData("RedisModule_CallReplyType_null", 1); - - int ret = SetPub_RedisCommand(&ctx, redisStrVec, 5); - CHECK_EQUAL(ret, REDISMODULE_OK); - mock().checkExpectations(); - CHECK_EQUAL(mock().getData("GET").getIntValue(), 0); - CHECK_EQUAL(mock().getData("MSET").getIntValue(), 1); - CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 0); - CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 1); - - delete []redisStrVec; - -} - TEST(exstring, setpub_command_no_key_replystr) { RedisModuleCtx ctx; @@ -684,38 +525,7 @@ TEST(exstring, setpub_command_no_key_replystr) CHECK_EQUAL(mock().getData("MSET").getIntValue(), 1); CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 1); CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 2); - - delete []redisStrVec; - -} - -TEST(exstring, setmpub_command_no_key_replynull) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[9]); - - redisStrVec[0] = (RedisModuleString *)0; - redisStrVec[1] = (RedisModuleString *)1; - redisStrVec[2] = (RedisModuleString *)2; - redisStrVec[3] = (RedisModuleString *)3; - redisStrVec[4] = (RedisModuleString *)4; - redisStrVec[5] = (RedisModuleString *)5; - redisStrVec[6] = (RedisModuleString *)6; - redisStrVec[7] = (RedisModuleString *)7; - redisStrVec[8] = (RedisModuleString *)8; - - mock().setData("RedisModule_KeyType_empty", 1); - mock().setData("RedisModule_CallReplyType_null", 1); - mock().setData("RedisModule_StringToLongLongCall_1", 1); - mock().setData("RedisModule_StringToLongLongCall_2", 2); - - int ret = SetMPub_RedisCommand(&ctx, redisStrVec, 9); - CHECK_EQUAL(ret, REDISMODULE_OK); - mock().checkExpectations(); - CHECK_EQUAL(0, mock().getData("GET").getIntValue()); - CHECK_EQUAL(1, mock().getData("MSET").getIntValue()); - CHECK_EQUAL(0, mock().getData("PUBLISH").getIntValue()); - CHECK_EQUAL(1, mock().getData("RedisModule_FreeCallReply").getIntValue()); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -747,6 +557,7 @@ TEST(exstring, setmpub_command_negative_key_val_count) CHECK_EQUAL(0, mock().getData("PUBLISH").getIntValue()); CHECK_EQUAL(1, mock().getData("RedisModule_ReplyWithError").getIntValue()); CHECK_EQUAL(0, mock().getData("RedisModule_FreeCallReply").getIntValue()); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -778,6 +589,7 @@ TEST(exstring, setmpub_command_negative_chan_msg_count) CHECK_EQUAL(0, mock().getData("PUBLISH").getIntValue()); CHECK_EQUAL(1, mock().getData("RedisModule_ReplyWithError").getIntValue()); CHECK_EQUAL(0, mock().getData("RedisModule_FreeCallReply").getIntValue()); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -809,6 +621,7 @@ TEST(exstring, setmpub_command_invalid_total_count) CHECK_EQUAL(0, mock().getData("PUBLISH").getIntValue()); CHECK_EQUAL(1, mock().getData("RedisModule_ReplyWithError").getIntValue()); CHECK_EQUAL(0, mock().getData("RedisModule_FreeCallReply").getIntValue()); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -839,6 +652,7 @@ TEST(exstring, setmpub_command_set) CHECK_EQUAL(1, mock().getData("MSET").getIntValue()); CHECK_EQUAL(1, mock().getData("PUBLISH").getIntValue()); CHECK_EQUAL(2, mock().getData("RedisModule_FreeCallReply").getIntValue()); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -871,6 +685,7 @@ TEST(exstring, setmpub_command_set_multipub) CHECK_EQUAL(1, mock().getData("MSET").getIntValue()); CHECK_EQUAL(2, mock().getData("PUBLISH").getIntValue()); CHECK_EQUAL(3, mock().getData("RedisModule_FreeCallReply").getIntValue()); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -900,6 +715,7 @@ TEST(exstring, setxxpub_command_has_no_key) CHECK_EQUAL(mock().getData("MSET").getIntValue(), 0); CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 0); CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 0); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -928,6 +744,7 @@ TEST(exstring, setxxpub_command_parameter_has_key_set) CHECK_EQUAL(mock().getData("MSET").getIntValue(), 0); CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 0); CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 0); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -957,6 +774,7 @@ TEST(exstring, setxxpub_command_has_key_string) CHECK_EQUAL(mock().getData("MSET").getIntValue(), 1); CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 1); CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 2); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -987,6 +805,7 @@ TEST(exstring, setnxpub_command_has_key_string) CHECK_EQUAL(mock().getData("MSET").getIntValue(), 0); CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 0); CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 0); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -1016,6 +835,7 @@ TEST(exstring, setnxpub_command_has_no_key) CHECK_EQUAL(mock().getData("MSET").getIntValue(), 1); CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 1); CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 2); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -1048,6 +868,7 @@ TEST(exstring, setiepub_command_has_no_key) CHECK_EQUAL(mock().getData("MSET").getIntValue(), 0); CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 0); CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 0); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -1080,37 +901,7 @@ TEST(exstring, setiepub_command_key_string_nosame) CHECK_EQUAL(mock().getData("MSET").getIntValue(), 0); CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 0); CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 1); - - delete []redisStrVec; - -} - -TEST(exstring, setiepub_command_key_same_string_replynull) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[6]); - - redisStrVec[0] = (RedisModuleString *)0; - redisStrVec[1] = (RedisModuleString *)1; - redisStrVec[2] = (RedisModuleString *)2; - redisStrVec[3] = (RedisModuleString *)3; - redisStrVec[4] = (RedisModuleString *)4; - redisStrVec[5] = (RedisModuleString *)5; - - mock().setData("RedisModule_KeyType_str", 1); - mock().setData("RedisModule_String_same", 1); - mock().setData("RedisModule_CallReplyType_null", 1); - - mock().expectOneCall("RedisModule_CloseKey"); - int ret = SetIEPub_RedisCommand(&ctx, redisStrVec, 6); - - CHECK_EQUAL(ret, REDISMODULE_OK); - mock().checkExpectations(); - CHECK_EQUAL(mock().getData("GET").getIntValue(), 1); - CHECK_EQUAL(mock().getData("MSET").getIntValue(), 1); - CHECK_EQUAL(mock().getData("RedisModule_ReplyWithNull").getIntValue(), 1); - CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 0); - CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 2); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -1142,6 +933,7 @@ TEST(exstring, setiepub_command_key_same_string_reply) CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 1); CHECK_EQUAL(mock().getData("RedisModule_ReplyWithCallReply").getIntValue(), 1); CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 3); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -1173,6 +965,7 @@ TEST(exstring, setnepub_command_has_no_key) CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 1); CHECK_EQUAL(mock().getData("RedisModule_ReplyWithCallReply").getIntValue(), 1); CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 3); + CHECK_EQUAL(mock().getData("RedisModule_AutoMemory").getIntValue(),1); delete []redisStrVec; @@ -1313,6 +1106,29 @@ TEST(exstring, deliepub) delete []redisStrVec; } +TEST(exstring, deliempub) +{ + RedisModuleCtx ctx; + RedisModuleString ** redisStrVec = new (RedisModuleString*[5]); + + redisStrVec[0] = (RedisModuleString *)1; + redisStrVec[1] = (RedisModuleString *)1; + redisStrVec[2] = (RedisModuleString *)1; + redisStrVec[3] = (RedisModuleString *)1; + redisStrVec[4] = (RedisModuleString *)1; + + mock().setData("RedisModule_OpenKey_have", 1); + mock().setData("RedisModule_KeyType_str", 1); + mock().setData("RedisModule_String_same", 1); + mock().setData("RedisModule_CallReplyType_null", 1); + + mock().expectOneCall("RedisModule_CloseKey"); + int ret = DelIEMPub_RedisCommand(&ctx, redisStrVec, 5); + CHECK_EQUAL(ret, REDISMODULE_OK); + mock().checkExpectations(); + delete []redisStrVec; +} + TEST(exstring, delnepub) { RedisModuleCtx ctx; @@ -1351,6 +1167,10 @@ TEST(exstring, delpub_command_parameter_number_incorrect) ret = DelIEPub_RedisCommand(&ctx, 0, 4); CHECK_EQUAL(ret, REDISMODULE_ERR); + ret = 0; + ret = DelIEMPub_RedisCommand(&ctx, 0, 4); + CHECK_EQUAL(ret, REDISMODULE_ERR); + ret = 0; ret = DelNEPub_RedisCommand(&ctx, 0, 8); CHECK_EQUAL(ret, REDISMODULE_ERR); @@ -1396,12 +1216,12 @@ TEST(exstring, delpub_command_reply_error) mock().setData("RedisModule_CallReplyType_err", 1); int ret = DelPub_RedisCommand(&ctx, redisStrVec, 5); - CHECK_EQUAL(ret, REDISMODULE_ERR); + CHECK_EQUAL(ret, REDISMODULE_OK); CHECK_EQUAL(mock().getData("GET").getIntValue(), 0); CHECK_EQUAL(mock().getData("UNLINK").getIntValue(), 1); CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 0); CHECK_EQUAL(mock().getData("RedisModule_ReplyWithCallReply").getIntValue(), 1); - CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 1); + CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 0); CHECK_EQUAL(mock().getData("RedisModule_ReplyWithError").getIntValue(), 0); delete []redisStrVec; @@ -1479,12 +1299,12 @@ TEST(exstring, delmpub_command_reply_error) mock().setData("RedisModule_StringToLongLongCall_2", 1); int ret = DelMPub_RedisCommand(&ctx, redisStrVec, 6); - CHECK_EQUAL(ret, REDISMODULE_ERR); + CHECK_EQUAL(ret, REDISMODULE_OK); CHECK_EQUAL(mock().getData("GET").getIntValue(), 0); CHECK_EQUAL(mock().getData("UNLINK").getIntValue(), 1); CHECK_EQUAL(mock().getData("PUBLISH").getIntValue(), 0); CHECK_EQUAL(mock().getData("RedisModule_ReplyWithCallReply").getIntValue(), 1); - CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 1); + CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 0); CHECK_EQUAL(mock().getData("RedisModule_ReplyWithError").getIntValue(), 0); delete []redisStrVec; @@ -1869,100 +1689,3 @@ TEST(exstring, delnepub_command_nosame_string_reply) delete []redisStrVec; } - -TEST(exstring, nget_command_parameter_number_incorrect) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[2]); - redisStrVec[0] = (RedisModuleString *)1; - redisStrVec[1] = (RedisModuleString *)1; - - int ret = NGet_RedisCommand(&ctx, redisStrVec, 3); - CHECK_EQUAL(ret, REDISMODULE_ERR); - - delete []redisStrVec; -} - -TEST(exstring, nget_command_zero_item) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[2]); - redisStrVec[0] = (RedisModuleString *)1; - redisStrVec[1] = (RedisModuleString *)1; - - mock().setData("RedisModule_CallReplyLength", 0); - int ret = NGet_RedisCommand(&ctx, redisStrVec, 2); - CHECK_EQUAL(ret, REDISMODULE_OK); - CHECK_EQUAL(mock().getData("KEYS").getIntValue(), 1); - CHECK_EQUAL(mock().getData("RedisModule_ReplyWithCallReply").getIntValue(), 1); - CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 1); - - delete []redisStrVec; -} - -TEST(exstring, nget_command_none_zero_items) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[2]); - redisStrVec[0] = (RedisModuleString *)1; - redisStrVec[1] = (RedisModuleString *)1; - - mock().setData("RedisModule_CallReplyLength", 3); - int ret = NGet_RedisCommand(&ctx, redisStrVec, 2); - CHECK_EQUAL(ret, REDISMODULE_OK); - CHECK_EQUAL(mock().getData("KEYS").getIntValue(), 1); - CHECK_EQUAL(mock().getData("MGET").getIntValue(), 1); - CHECK_EQUAL(mock().getData("RedisModule_ReplyWithArray").getIntValue(), 3*2); - CHECK_EQUAL(mock().getData("RedisModule_ReplyWithString").getIntValue(), 3*2); - CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 2); - - delete []redisStrVec; -} - -TEST(exstring, ndel_command_parameter_parameter_number_incorrect) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[2]); - redisStrVec[0] = (RedisModuleString *)1; - redisStrVec[1] = (RedisModuleString *)1; - - int ret = NDel_RedisCommand(&ctx, redisStrVec, 3); - CHECK_EQUAL(ret, REDISMODULE_ERR); - - delete []redisStrVec; -} - -TEST(exstring, ndel_command_zero_item) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[2]); - redisStrVec[0] = (RedisModuleString *)1; - redisStrVec[1] = (RedisModuleString *)1; - - mock().setData("RedisModule_CallReplyLength", 0); - int ret = NDel_RedisCommand(&ctx, redisStrVec, 2); - CHECK_EQUAL(ret, REDISMODULE_OK); - CHECK_EQUAL(mock().getData("KEYS").getIntValue(), 1); - CHECK_EQUAL(mock().getData("RedisModule_ReplyWithLongLong").getIntValue(), 0); - CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 1); - - delete []redisStrVec; -} - -TEST(exstring, ndel_command_none_zero_items) -{ - RedisModuleCtx ctx; - RedisModuleString ** redisStrVec = new (RedisModuleString*[2]); - redisStrVec[0] = (RedisModuleString *)1; - redisStrVec[1] = (RedisModuleString *)1; - - mock().setData("RedisModule_CallReplyLength", 3); - int ret = NDel_RedisCommand(&ctx, redisStrVec, 2); - CHECK_EQUAL(ret, REDISMODULE_OK); - CHECK_EQUAL(mock().getData("KEYS").getIntValue(), 1); - CHECK_EQUAL(mock().getData("UNLINK").getIntValue(), 1); - CHECK_EQUAL(mock().getData("RedisModule_ReplyWithCallReply").getIntValue(), 1); - CHECK_EQUAL(mock().getData("RedisModule_FreeCallReply").getIntValue(), 2); - - delete []redisStrVec; -}