Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
04340e1f
Commit
04340e1f
authored
Aug 03, 2016
by
antirez
Browse files
Modules: initial draft for a testing module.
parent
7829e4ed
Changes
3
Show whitespace changes
Inline
Side-by-side
src/module.c
View file @
04340e1f
...
...
@@ -766,6 +766,10 @@ const char *RM_StringPtrLen(const RedisModuleString *str, size_t *len) {
return str->ptr;
}
/* --------------------------------------------------------------------------
* Higher level string operations
* ------------------------------------------------------------------------- */
/* Convert the string into a long long integer, storing it at `*ll`.
* Returns REDISMODULE_OK on success. If the string can't be parsed
* as a valid, strict long long (no spaces before/after), REDISMODULE_ERR
...
...
@@ -783,6 +787,13 @@ int RM_StringToDouble(const RedisModuleString *str, double *d) {
return (retval == C_OK) ? REDISMODULE_OK : REDISMODULE_ERR;
}
/* Compare two string objects, returning -1, 0 or 1 respectively if
* a < b, a == b, a > b. Strings are compared byte by byte as two
* binary blobs without any encoding care / collation attempt. */
int RM_StringCompare(RedisModuleString *a, RedisModuleString *b) {
return compareStringObjects(a,b);
}
/* Return the (possibly modified in encoding) input 'str' object if
* the string is unshared, otherwise NULL is returned. */
RedisModuleString *moduleAssertUnsharedString(RedisModuleString *str) {
...
...
@@ -2940,100 +2951,9 @@ int moduleRegisterApi(const char *funcname, void *funcptr) {
#define REGISTER_API(name) \
moduleRegisterApi("RedisModule_" #name, (void *)(unsigned long)RM_ ## name)
/* Register all the APIs we export. */
void moduleRegisterCoreAPI(void) {
server.moduleapi = dictCreate(&moduleAPIDictType,NULL);
REGISTER_API(Alloc);
REGISTER_API(Calloc);
REGISTER_API(Realloc);
REGISTER_API(Free);
REGISTER_API(Strdup);
REGISTER_API(CreateCommand);
REGISTER_API(SetModuleAttribs);
REGISTER_API(WrongArity);
REGISTER_API(ReplyWithLongLong);
REGISTER_API(ReplyWithError);
REGISTER_API(ReplyWithSimpleString);
REGISTER_API(ReplyWithArray);
REGISTER_API(ReplySetArrayLength);
REGISTER_API(ReplyWithString);
REGISTER_API(ReplyWithStringBuffer);
REGISTER_API(ReplyWithNull);
REGISTER_API(ReplyWithCallReply);
REGISTER_API(ReplyWithDouble);
REGISTER_API(GetSelectedDb);
REGISTER_API(SelectDb);
REGISTER_API(OpenKey);
REGISTER_API(CloseKey);
REGISTER_API(KeyType);
REGISTER_API(ValueLength);
REGISTER_API(ListPush);
REGISTER_API(ListPop);
REGISTER_API(StringToLongLong);
REGISTER_API(StringToDouble);
REGISTER_API(Call);
REGISTER_API(CallReplyProto);
REGISTER_API(FreeCallReply);
REGISTER_API(CallReplyInteger);
REGISTER_API(CallReplyType);
REGISTER_API(CallReplyLength);
REGISTER_API(CallReplyArrayElement);
REGISTER_API(CallReplyStringPtr);
REGISTER_API(CreateStringFromCallReply);
REGISTER_API(CreateString);
REGISTER_API(CreateStringFromLongLong);
REGISTER_API(CreateStringFromString);
REGISTER_API(FreeString);
REGISTER_API(StringPtrLen);
REGISTER_API(AutoMemory);
REGISTER_API(Replicate);
REGISTER_API(ReplicateVerbatim);
REGISTER_API(DeleteKey);
REGISTER_API(StringSet);
REGISTER_API(StringDMA);
REGISTER_API(StringTruncate);
REGISTER_API(SetExpire);
REGISTER_API(GetExpire);
REGISTER_API(ZsetAdd);
REGISTER_API(ZsetIncrby);
REGISTER_API(ZsetScore);
REGISTER_API(ZsetRem);
REGISTER_API(ZsetRangeStop);
REGISTER_API(ZsetFirstInScoreRange);
REGISTER_API(ZsetLastInScoreRange);
REGISTER_API(ZsetFirstInLexRange);
REGISTER_API(ZsetLastInLexRange);
REGISTER_API(ZsetRangeCurrentElement);
REGISTER_API(ZsetRangeNext);
REGISTER_API(ZsetRangePrev);
REGISTER_API(ZsetRangeEndReached);
REGISTER_API(HashSet);
REGISTER_API(HashGet);
REGISTER_API(IsKeysPositionRequest);
REGISTER_API(KeyAtPos);
REGISTER_API(GetClientId);
REGISTER_API(PoolAlloc);
REGISTER_API(CreateDataType);
REGISTER_API(ModuleTypeSetValue);
REGISTER_API(ModuleTypeGetType);
REGISTER_API(ModuleTypeGetValue);
REGISTER_API(SaveUnsigned);
REGISTER_API(LoadUnsigned);
REGISTER_API(SaveSigned);
REGISTER_API(LoadSigned);
REGISTER_API(SaveString);
REGISTER_API(SaveStringBuffer);
REGISTER_API(LoadString);
REGISTER_API(LoadStringBuffer);
REGISTER_API(SaveDouble);
REGISTER_API(LoadDouble);
REGISTER_API(EmitAOF);
REGISTER_API(Log);
REGISTER_API(StringAppendBuffer);
REGISTER_API(RetainString);
}
/* Global initialization at Redis startup. */
void moduleRegisterCoreAPI(void);
void moduleInitModulesSystem(void) {
server.loadmodule_queue = listCreate();
modules = dictCreate(&modulesDictType,NULL);
...
...
@@ -3222,3 +3142,98 @@ void moduleCommand(client *c) {
addReply(c,shared.syntaxerr);
}
}
/* Register all the APIs we export. Keep this function at the end of the
* file so that's easy to seek it to add new entries. */
void moduleRegisterCoreAPI(void) {
server.moduleapi = dictCreate(&moduleAPIDictType,NULL);
REGISTER_API(Alloc);
REGISTER_API(Calloc);
REGISTER_API(Realloc);
REGISTER_API(Free);
REGISTER_API(Strdup);
REGISTER_API(CreateCommand);
REGISTER_API(SetModuleAttribs);
REGISTER_API(WrongArity);
REGISTER_API(ReplyWithLongLong);
REGISTER_API(ReplyWithError);
REGISTER_API(ReplyWithSimpleString);
REGISTER_API(ReplyWithArray);
REGISTER_API(ReplySetArrayLength);
REGISTER_API(ReplyWithString);
REGISTER_API(ReplyWithStringBuffer);
REGISTER_API(ReplyWithNull);
REGISTER_API(ReplyWithCallReply);
REGISTER_API(ReplyWithDouble);
REGISTER_API(GetSelectedDb);
REGISTER_API(SelectDb);
REGISTER_API(OpenKey);
REGISTER_API(CloseKey);
REGISTER_API(KeyType);
REGISTER_API(ValueLength);
REGISTER_API(ListPush);
REGISTER_API(ListPop);
REGISTER_API(StringToLongLong);
REGISTER_API(StringToDouble);
REGISTER_API(Call);
REGISTER_API(CallReplyProto);
REGISTER_API(FreeCallReply);
REGISTER_API(CallReplyInteger);
REGISTER_API(CallReplyType);
REGISTER_API(CallReplyLength);
REGISTER_API(CallReplyArrayElement);
REGISTER_API(CallReplyStringPtr);
REGISTER_API(CreateStringFromCallReply);
REGISTER_API(CreateString);
REGISTER_API(CreateStringFromLongLong);
REGISTER_API(CreateStringFromString);
REGISTER_API(FreeString);
REGISTER_API(StringPtrLen);
REGISTER_API(AutoMemory);
REGISTER_API(Replicate);
REGISTER_API(ReplicateVerbatim);
REGISTER_API(DeleteKey);
REGISTER_API(StringSet);
REGISTER_API(StringDMA);
REGISTER_API(StringTruncate);
REGISTER_API(SetExpire);
REGISTER_API(GetExpire);
REGISTER_API(ZsetAdd);
REGISTER_API(ZsetIncrby);
REGISTER_API(ZsetScore);
REGISTER_API(ZsetRem);
REGISTER_API(ZsetRangeStop);
REGISTER_API(ZsetFirstInScoreRange);
REGISTER_API(ZsetLastInScoreRange);
REGISTER_API(ZsetFirstInLexRange);
REGISTER_API(ZsetLastInLexRange);
REGISTER_API(ZsetRangeCurrentElement);
REGISTER_API(ZsetRangeNext);
REGISTER_API(ZsetRangePrev);
REGISTER_API(ZsetRangeEndReached);
REGISTER_API(HashSet);
REGISTER_API(HashGet);
REGISTER_API(IsKeysPositionRequest);
REGISTER_API(KeyAtPos);
REGISTER_API(GetClientId);
REGISTER_API(PoolAlloc);
REGISTER_API(CreateDataType);
REGISTER_API(ModuleTypeSetValue);
REGISTER_API(ModuleTypeGetType);
REGISTER_API(ModuleTypeGetValue);
REGISTER_API(SaveUnsigned);
REGISTER_API(LoadUnsigned);
REGISTER_API(SaveSigned);
REGISTER_API(LoadSigned);
REGISTER_API(SaveString);
REGISTER_API(SaveStringBuffer);
REGISTER_API(LoadString);
REGISTER_API(LoadStringBuffer);
REGISTER_API(SaveDouble);
REGISTER_API(LoadDouble);
REGISTER_API(EmitAOF);
REGISTER_API(Log);
REGISTER_API(StringAppendBuffer);
REGISTER_API(RetainString);
REGISTER_API(StringCompare);
}
src/modules/testmodule.c
0 → 100644
View file @
04340e1f
/* Module designed to test the Redis modules subsystem.
*
* -----------------------------------------------------------------------------
*
* Copyright (c) 2016, Salvatore Sanfilippo <antirez at gmail dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "../redismodule.h"
/* ------------------------------- Test units ------------------------------- */
/* TEST.STRING.APPEND -- Test appending to an existing string object. */
int
TestStringAppend
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
RedisModuleString
*
s
=
RedisModule_CreateString
(
ctx
,
"foo"
,
3
);
RedisModule_StringAppendBuffer
(
ctx
,
s
,
"bar"
,
3
);
RedisModule_ReplyWithString
(
ctx
,
s
);
RedisModule_FreeString
(
ctx
,
s
);
return
REDISMODULE_OK
;
}
/* TEST.STRING.APPEND.AM -- Test append with retain when auto memory is on. */
int
TestStringAppendAM
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
RedisModule_AutoMemory
(
ctx
);
RedisModuleString
*
s
=
RedisModule_CreateString
(
ctx
,
"foo"
,
3
);
RedisModule_RetainString
(
ctx
,
s
);
RedisModule_StringAppendBuffer
(
ctx
,
s
,
"bar"
,
3
);
RedisModule_ReplyWithString
(
ctx
,
s
);
RedisModule_FreeString
(
ctx
,
s
);
return
REDISMODULE_OK
;
}
/* ----------------------------- Test framework ----------------------------- */
/* Return 1 if the reply matches the specified string, otherwise log errors
* in the server log and return 0. */
int
TestAssertStringReply
(
RedisModuleCtx
*
ctx
,
RedisModuleCallReply
*
reply
,
char
*
str
,
size_t
len
)
{
RedisModuleString
*
mystr
,
*
expected
;
if
(
RedisModule_CallReplyType
(
reply
)
!=
REDISMODULE_REPLY_STRING
)
{
RedisModule_Log
(
ctx
,
"warning"
,
"Unexpected reply type %d"
,
RedisModule_CallReplyType
(
reply
));
return
0
;
}
mystr
=
RedisModule_CreateStringFromCallReply
(
reply
);
expected
=
RedisModule_CreateString
(
ctx
,
str
,
len
);
if
(
RedisModule_StringCompare
(
mystr
,
expected
)
!=
0
)
{
const
char
*
mystr_ptr
=
RedisModule_StringPtrLen
(
mystr
,
NULL
);
const
char
*
expected_ptr
=
RedisModule_StringPtrLen
(
expected
,
NULL
);
RedisModule_Log
(
ctx
,
"warning"
,
"Unexpected string reply '%s' (instead of '%s')"
,
mystr_ptr
,
expected_ptr
);
return
0
;
}
return
1
;
}
#define T(name,...) \
do { \
RedisModule_Log(ctx,"warning","Testing %s", name); \
reply = RedisModule_Call(ctx,name,__VA_ARGS__); \
} while (0);
/* TEST.IT -- Run all the tests. */
int
TestIt
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
RedisModule_AutoMemory
(
ctx
);
RedisModuleCallReply
*
reply
;
T
(
"test.string.append"
,
""
);
if
(
!
TestAssertStringReply
(
ctx
,
reply
,
"foobar"
,
6
))
goto
fail
;
T
(
"test.string.append.am"
,
""
);
if
(
!
TestAssertStringReply
(
ctx
,
reply
,
"foobar"
,
6
))
goto
fail
;
RedisModule_ReplyWithSimpleString
(
ctx
,
"ALL TESTS PASSED"
);
return
REDISMODULE_OK
;
fail:
RedisModule_ReplyWithSimpleString
(
ctx
,
"SOME TEST NOT PASSED! Check server logs"
);
return
REDISMODULE_OK
;
}
int
RedisModule_OnLoad
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
if
(
RedisModule_Init
(
ctx
,
"test"
,
1
,
REDISMODULE_APIVER_1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.string.append"
,
TestStringAppend
,
"write deny-oom"
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.string.append.am"
,
TestStringAppendAM
,
"write deny-oom"
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.it"
,
TestIt
,
"readonly"
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
return
REDISMODULE_OK
;
}
src/redismodule.h
View file @
04340e1f
...
...
@@ -186,6 +186,7 @@ double REDISMODULE_API_FUNC(RedisModule_LoadDouble)(RedisModuleIO *io);
void
REDISMODULE_API_FUNC
(
RedisModule_Log
)(
RedisModuleCtx
*
ctx
,
const
char
*
level
,
const
char
*
fmt
,
...);
int
REDISMODULE_API_FUNC
(
RedisModule_StringAppendBuffer
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
*
str
,
const
char
*
buf
,
size_t
len
);
void
REDISMODULE_API_FUNC
(
RedisModule_RetainString
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
*
str
);
int
REDISMODULE_API_FUNC
(
RedisModule_StringCompare
)(
RedisModuleString
*
a
,
RedisModuleString
*
b
);
/* This is included inline inside each Redis module. */
static
int
RedisModule_Init
(
RedisModuleCtx
*
ctx
,
const
char
*
name
,
int
ver
,
int
apiver
)
__attribute__
((
unused
));
...
...
@@ -281,6 +282,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
Log
);
REDISMODULE_GET_API
(
StringAppendBuffer
);
REDISMODULE_GET_API
(
RetainString
);
REDISMODULE_GET_API
(
StringCompare
);
RedisModule_SetModuleAttribs
(
ctx
,
name
,
ver
,
apiver
);
return
REDISMODULE_OK
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment