Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
0f026af1
Commit
0f026af1
authored
Nov 06, 2019
by
antirez
Browse files
Merge branch 'unstable' of github.com:/antirez/redis into unstable
parents
8b2c0f90
a15a5d70
Changes
27
Show whitespace changes
Inline
Side-by-side
tests/modules/hooks.c
View file @
0f026af1
...
@@ -30,36 +30,227 @@
...
@@ -30,36 +30,227 @@
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#define REDISMODULE_EXPERIMENTAL_API
#include "redismodule.h"
#include "redismodule.h"
#include <stdio.h>
#include <string.h>
/* We need to store events to be able to test and see what we got, and we can't
* store them in the key-space since that would mess up rdb loading (duplicates)
* and be lost of flushdb. */
RedisModuleDict
*
event_log
=
NULL
;
typedef
struct
EventElement
{
long
count
;
RedisModuleString
*
last_val_string
;
long
last_val_int
;
}
EventElement
;
void
LogStringEvent
(
RedisModuleCtx
*
ctx
,
const
char
*
keyname
,
const
char
*
data
)
{
EventElement
*
event
=
RedisModule_DictGetC
(
event_log
,
(
void
*
)
keyname
,
strlen
(
keyname
),
NULL
);
if
(
!
event
)
{
event
=
RedisModule_Alloc
(
sizeof
(
EventElement
));
memset
(
event
,
0
,
sizeof
(
EventElement
));
RedisModule_DictSetC
(
event_log
,
(
void
*
)
keyname
,
strlen
(
keyname
),
event
);
}
if
(
event
->
last_val_string
)
RedisModule_FreeString
(
ctx
,
event
->
last_val_string
);
event
->
last_val_string
=
RedisModule_CreateString
(
ctx
,
data
,
strlen
(
data
));
event
->
count
++
;
}
void
LogNumericEvent
(
RedisModuleCtx
*
ctx
,
const
char
*
keyname
,
long
data
)
{
REDISMODULE_NOT_USED
(
ctx
);
EventElement
*
event
=
RedisModule_DictGetC
(
event_log
,
(
void
*
)
keyname
,
strlen
(
keyname
),
NULL
);
if
(
!
event
)
{
event
=
RedisModule_Alloc
(
sizeof
(
EventElement
));
memset
(
event
,
0
,
sizeof
(
EventElement
));
RedisModule_DictSetC
(
event_log
,
(
void
*
)
keyname
,
strlen
(
keyname
),
event
);
}
event
->
last_val_int
=
data
;
event
->
count
++
;
}
void
FreeEvent
(
RedisModuleCtx
*
ctx
,
EventElement
*
event
)
{
if
(
event
->
last_val_string
)
RedisModule_FreeString
(
ctx
,
event
->
last_val_string
);
RedisModule_Free
(
event
);
}
int
cmdEventCount
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
if
(
argc
!=
2
){
RedisModule_WrongArity
(
ctx
);
return
REDISMODULE_OK
;
}
EventElement
*
event
=
RedisModule_DictGet
(
event_log
,
argv
[
1
],
NULL
);
RedisModule_ReplyWithLongLong
(
ctx
,
event
?
event
->
count
:
0
);
return
REDISMODULE_OK
;
}
int
cmdEventLast
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
if
(
argc
!=
2
){
RedisModule_WrongArity
(
ctx
);
return
REDISMODULE_OK
;
}
EventElement
*
event
=
RedisModule_DictGet
(
event_log
,
argv
[
1
],
NULL
);
if
(
event
&&
event
->
last_val_string
)
RedisModule_ReplyWithString
(
ctx
,
event
->
last_val_string
);
else
if
(
event
)
RedisModule_ReplyWithLongLong
(
ctx
,
event
->
last_val_int
);
else
RedisModule_ReplyWithNull
(
ctx
);
return
REDISMODULE_OK
;
}
void
clearEvents
(
RedisModuleCtx
*
ctx
)
{
RedisModuleString
*
key
;
EventElement
*
event
;
RedisModuleDictIter
*
iter
=
RedisModule_DictIteratorStart
(
event_log
,
"^"
,
NULL
);
while
((
key
=
RedisModule_DictNext
(
ctx
,
iter
,
(
void
**
)
&
event
))
!=
NULL
)
{
event
->
count
=
0
;
event
->
last_val_int
=
0
;
if
(
event
->
last_val_string
)
RedisModule_FreeString
(
ctx
,
event
->
last_val_string
);
event
->
last_val_string
=
NULL
;
RedisModule_DictDel
(
event_log
,
key
,
NULL
);
RedisModule_Free
(
event
);
}
RedisModule_DictIteratorStop
(
iter
);
}
int
cmdEventsClear
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argc
);
REDISMODULE_NOT_USED
(
argv
);
clearEvents
(
ctx
);
return
REDISMODULE_OK
;
}
/* Client state change callback. */
/* Client state change callback. */
void
clientChangeCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
void
clientChangeCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
{
{
REDISMODULE_NOT_USED
(
ctx
);
REDISMODULE_NOT_USED
(
e
);
REDISMODULE_NOT_USED
(
e
);
RedisModuleClientInfo
*
ci
=
data
;
RedisModuleClientInfo
*
ci
=
data
;
char
*
keyname
=
(
sub
==
REDISMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED
)
?
char
*
keyname
=
(
sub
==
REDISMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED
)
?
"connected"
:
"disconnected"
;
"client-connected"
:
"client-disconnected"
;
RedisModuleCallReply
*
reply
;
LogNumericEvent
(
ctx
,
keyname
,
ci
->
id
);
RedisModule_SelectDb
(
ctx
,
9
);
reply
=
RedisModule_Call
(
ctx
,
"RPUSH"
,
"cl"
,
keyname
,(
long
)
ci
->
id
);
RedisModule_FreeCallReply
(
reply
);
}
}
void
flushdbCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
void
flushdbCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
{
{
REDISMODULE_NOT_USED
(
ctx
);
REDISMODULE_NOT_USED
(
e
);
REDISMODULE_NOT_USED
(
e
);
RedisModuleFlushInfo
*
fi
=
data
;
RedisModuleFlushInfo
*
fi
=
data
;
char
*
keyname
=
(
sub
==
REDISMODULE_SUBEVENT_FLUSHDB_START
)
?
char
*
keyname
=
(
sub
==
REDISMODULE_SUBEVENT_FLUSHDB_START
)
?
"flush-start"
:
"flush-end"
;
"flush-start"
:
"flush-end"
;
RedisModuleCallReply
*
reply
;
LogNumericEvent
(
ctx
,
keyname
,
fi
->
dbnum
);
RedisModule_SelectDb
(
ctx
,
9
);
}
reply
=
RedisModule_Call
(
ctx
,
"RPUSH"
,
"cl"
,
keyname
,(
long
)
fi
->
dbnum
);
RedisModule_FreeCallReply
(
reply
);
void
roleChangeCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
{
REDISMODULE_NOT_USED
(
e
);
REDISMODULE_NOT_USED
(
data
);
RedisModuleReplicationInfo
*
ri
=
data
;
char
*
keyname
=
(
sub
==
REDISMODULE_EVENT_REPLROLECHANGED_NOW_MASTER
)
?
"role-master"
:
"role-replica"
;
LogStringEvent
(
ctx
,
keyname
,
ri
->
masterhost
);
}
void
replicationChangeCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
{
REDISMODULE_NOT_USED
(
e
);
REDISMODULE_NOT_USED
(
data
);
char
*
keyname
=
(
sub
==
REDISMODULE_SUBEVENT_REPLICA_CHANGE_ONLINE
)
?
"replica-online"
:
"replica-offline"
;
LogNumericEvent
(
ctx
,
keyname
,
0
);
}
void
rasterLinkChangeCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
{
REDISMODULE_NOT_USED
(
e
);
REDISMODULE_NOT_USED
(
data
);
char
*
keyname
=
(
sub
==
REDISMODULE_SUBEVENT_MASTER_LINK_UP
)
?
"masterlink-up"
:
"masterlink-down"
;
LogNumericEvent
(
ctx
,
keyname
,
0
);
}
void
persistenceCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
{
REDISMODULE_NOT_USED
(
e
);
REDISMODULE_NOT_USED
(
data
);
char
*
keyname
=
NULL
;
switch
(
sub
)
{
case
REDISMODULE_SUBEVENT_PERSISTENCE_RDB_START
:
keyname
=
"persistence-rdb-start"
;
break
;
case
REDISMODULE_SUBEVENT_PERSISTENCE_AOF_START
:
keyname
=
"persistence-aof-start"
;
break
;
case
REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_RDB_START
:
keyname
=
"persistence-syncrdb-start"
;
break
;
case
REDISMODULE_SUBEVENT_PERSISTENCE_ENDED
:
keyname
=
"persistence-end"
;
break
;
case
REDISMODULE_SUBEVENT_PERSISTENCE_FAILED
:
keyname
=
"persistence-failed"
;
break
;
}
/* modifying the keyspace from the fork child is not an option, using log instead */
RedisModule_Log
(
ctx
,
"warning"
,
"module-event-%s"
,
keyname
);
if
(
sub
==
REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_RDB_START
)
LogNumericEvent
(
ctx
,
keyname
,
0
);
}
void
loadingCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
{
REDISMODULE_NOT_USED
(
e
);
REDISMODULE_NOT_USED
(
data
);
char
*
keyname
=
NULL
;
switch
(
sub
)
{
case
REDISMODULE_SUBEVENT_LOADING_RDB_START
:
keyname
=
"loading-rdb-start"
;
break
;
case
REDISMODULE_SUBEVENT_LOADING_AOF_START
:
keyname
=
"loading-aof-start"
;
break
;
case
REDISMODULE_SUBEVENT_LOADING_REPL_START
:
keyname
=
"loading-repl-start"
;
break
;
case
REDISMODULE_SUBEVENT_LOADING_ENDED
:
keyname
=
"loading-end"
;
break
;
case
REDISMODULE_SUBEVENT_LOADING_FAILED
:
keyname
=
"loading-failed"
;
break
;
}
LogNumericEvent
(
ctx
,
keyname
,
0
);
}
void
loadingProgressCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
{
REDISMODULE_NOT_USED
(
e
);
RedisModuleLoadingProgress
*
ei
=
data
;
char
*
keyname
=
(
sub
==
REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB
)
?
"loading-progress-rdb"
:
"loading-progress-aof"
;
LogNumericEvent
(
ctx
,
keyname
,
ei
->
progress
);
}
void
shutdownCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
{
REDISMODULE_NOT_USED
(
e
);
REDISMODULE_NOT_USED
(
data
);
REDISMODULE_NOT_USED
(
sub
);
RedisModule_Log
(
ctx
,
"warning"
,
"module-event-%s"
,
"shutdown"
);
}
void
cronLoopCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
{
REDISMODULE_NOT_USED
(
e
);
REDISMODULE_NOT_USED
(
sub
);
RedisModuleCronLoop
*
ei
=
data
;
LogNumericEvent
(
ctx
,
"cron-loop"
,
ei
->
hz
);
}
void
moduleChangeCallback
(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
e
,
uint64_t
sub
,
void
*
data
)
{
REDISMODULE_NOT_USED
(
e
);
RedisModuleModuleChange
*
ei
=
data
;
char
*
keyname
=
(
sub
==
REDISMODULE_SUBEVENT_MODULE_LOADED
)
?
"module-loaded"
:
"module-unloaded"
;
LogStringEvent
(
ctx
,
keyname
,
ei
->
module_name
);
}
}
/* This function must be present on each Redis module. It is used in order to
/* This function must be present on each Redis module. It is used in order to
...
@@ -71,9 +262,50 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
...
@@ -71,9 +262,50 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
if
(
RedisModule_Init
(
ctx
,
"testhook"
,
1
,
REDISMODULE_APIVER_1
)
if
(
RedisModule_Init
(
ctx
,
"testhook"
,
1
,
REDISMODULE_APIVER_1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
/* replication related hooks */
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModuleEvent_ReplicationRoleChanged
,
roleChangeCallback
);
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModuleEvent_ReplicaChange
,
replicationChangeCallback
);
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModuleEvent_MasterLinkChange
,
rasterLinkChangeCallback
);
/* persistence related hooks */
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModuleEvent_Persistence
,
persistenceCallback
);
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModuleEvent_Loading
,
loadingCallback
);
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModuleEvent_LoadingProgress
,
loadingProgressCallback
);
/* other hooks */
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModuleEvent_ClientChange
,
clientChangeCallback
);
RedisModuleEvent_ClientChange
,
clientChangeCallback
);
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModuleEvent_FlushDB
,
flushdbCallback
);
RedisModuleEvent_FlushDB
,
flushdbCallback
);
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModuleEvent_Shutdown
,
shutdownCallback
);
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModuleEvent_CronLoop
,
cronLoopCallback
);
RedisModule_SubscribeToServerEvent
(
ctx
,
RedisModuleEvent_ModuleChange
,
moduleChangeCallback
);
event_log
=
RedisModule_CreateDict
(
ctx
);
if
(
RedisModule_CreateCommand
(
ctx
,
"hooks.event_count"
,
cmdEventCount
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"hooks.event_last"
,
cmdEventLast
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"hooks.clear"
,
cmdEventsClear
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
return
REDISMODULE_OK
;
return
REDISMODULE_OK
;
}
}
int
RedisModule_OnUnload
(
RedisModuleCtx
*
ctx
)
{
clearEvents
(
ctx
);
RedisModule_FreeDict
(
ctx
,
event_log
);
event_log
=
NULL
;
return
REDISMODULE_OK
;
}
tests/modules/misc.c
View file @
0f026af1
...
@@ -40,6 +40,65 @@ int test_call_info(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
...
@@ -40,6 +40,65 @@ int test_call_info(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
return
REDISMODULE_OK
;
return
REDISMODULE_OK
;
}
}
int
test_flushall
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
RedisModule_ResetDataset
(
1
,
0
);
RedisModule_ReplyWithCString
(
ctx
,
"Ok"
);
return
REDISMODULE_OK
;
}
int
test_dbsize
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
long
long
ll
=
RedisModule_DbSize
(
ctx
);
RedisModule_ReplyWithLongLong
(
ctx
,
ll
);
return
REDISMODULE_OK
;
}
int
test_randomkey
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
RedisModuleString
*
str
=
RedisModule_RandomKey
(
ctx
);
RedisModule_ReplyWithString
(
ctx
,
str
);
RedisModule_FreeString
(
ctx
,
str
);
return
REDISMODULE_OK
;
}
int
test_getlru
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
if
(
argc
<
2
)
{
RedisModule_WrongArity
(
ctx
);
return
REDISMODULE_OK
;
}
RedisModuleString
*
keyname
=
argv
[
1
];
RedisModuleKey
*
key
=
RedisModule_OpenKey
(
ctx
,
keyname
,
REDISMODULE_READ
|
REDISMODULE_OPEN_KEY_NOTOUCH
);
long
long
lru
,
lfu
;
RedisModule_GetLRUOrLFU
(
key
,
&
lfu
,
&
lru
);
RedisModule_ReplyWithLongLong
(
ctx
,
lru
);
RedisModule_CloseKey
(
key
);
return
REDISMODULE_OK
;
}
int
test_setlru
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
if
(
argc
<
3
)
{
RedisModule_WrongArity
(
ctx
);
return
REDISMODULE_OK
;
}
RedisModuleString
*
keyname
=
argv
[
1
];
RedisModuleKey
*
key
=
RedisModule_OpenKey
(
ctx
,
keyname
,
REDISMODULE_WRITE
|
REDISMODULE_OPEN_KEY_NOTOUCH
);
long
long
lru
;
RedisModule_StringToLongLong
(
argv
[
2
],
&
lru
);
RedisModule_SetLRUOrLFU
(
key
,
-
1
,
lru
);
RedisModule_ReplyWithCString
(
ctx
,
"Ok"
);
RedisModule_CloseKey
(
key
);
return
REDISMODULE_OK
;
}
int
RedisModule_OnLoad
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
int
RedisModule_OnLoad
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
REDISMODULE_NOT_USED
(
argc
);
...
@@ -50,6 +109,16 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
...
@@ -50,6 +109,16 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
return
REDISMODULE_ERR
;
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.call_info"
,
test_call_info
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
if
(
RedisModule_CreateCommand
(
ctx
,
"test.call_info"
,
test_call_info
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.flushall"
,
test_flushall
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.dbsize"
,
test_dbsize
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.randomkey"
,
test_randomkey
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.setlru"
,
test_setlru
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.getlru"
,
test_getlru
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
return
REDISMODULE_OK
;
return
REDISMODULE_OK
;
}
}
tests/modules/testrdb.c
View file @
0f026af1
...
@@ -15,11 +15,16 @@ RedisModuleString *after_str = NULL;
...
@@ -15,11 +15,16 @@ RedisModuleString *after_str = NULL;
void
*
testrdb_type_load
(
RedisModuleIO
*
rdb
,
int
encver
)
{
void
*
testrdb_type_load
(
RedisModuleIO
*
rdb
,
int
encver
)
{
int
count
=
RedisModule_LoadSigned
(
rdb
);
int
count
=
RedisModule_LoadSigned
(
rdb
);
RedisModuleString
*
str
=
RedisModule_LoadString
(
rdb
);
float
f
=
RedisModule_LoadFloat
(
rdb
);
long
double
ld
=
RedisModule_LoadLongDouble
(
rdb
);
if
(
RedisModule_IsIOError
(
rdb
))
if
(
RedisModule_IsIOError
(
rdb
))
return
NULL
;
return
NULL
;
/* Using the values only after checking for io errors. */
assert
(
count
==
1
);
assert
(
count
==
1
);
assert
(
encver
==
1
);
assert
(
encver
==
1
);
RedisModuleString
*
str
=
RedisModule_LoadString
(
rdb
);
assert
(
f
==
1
.
5
f
);
assert
(
ld
==
0
.
333333333333333333L
);
return
str
;
return
str
;
}
}
...
@@ -27,6 +32,8 @@ void testrdb_type_save(RedisModuleIO *rdb, void *value) {
...
@@ -27,6 +32,8 @@ void testrdb_type_save(RedisModuleIO *rdb, void *value) {
RedisModuleString
*
str
=
(
RedisModuleString
*
)
value
;
RedisModuleString
*
str
=
(
RedisModuleString
*
)
value
;
RedisModule_SaveSigned
(
rdb
,
1
);
RedisModule_SaveSigned
(
rdb
,
1
);
RedisModule_SaveString
(
rdb
,
str
);
RedisModule_SaveString
(
rdb
,
str
);
RedisModule_SaveFloat
(
rdb
,
1
.
5
);
RedisModule_SaveLongDouble
(
rdb
,
0
.
333333333333333333L
);
}
}
void
testrdb_aux_save
(
RedisModuleIO
*
rdb
,
int
when
)
{
void
testrdb_aux_save
(
RedisModuleIO
*
rdb
,
int
when
)
{
...
...
tests/unit/moduleapi/blockonkeys.tcl
0 → 100644
View file @
0f026af1
set testmodule
[
file normalize tests/modules/blockonkeys.so
]
start_server
{
tags
{
"modules"
}}
{
r module load $testmodule
test
{
Module client blocked on keys
(
no metadata
)
: No block
}
{
r del k
r fsl.push k 33
r fsl.push k 34
r fsl.bpop2 k 0
}
{
34 33
}
test
{
Module client blocked on keys
(
no metadata
)
: Timeout
}
{
r del k
set rd
[
redis_deferring_client
]
r fsl.push k 33
$rd fsl.bpop2 k 1
assert_equal
{
Request timedout
}
[
$rd
read
]
}
test
{
Module client blocked on keys
(
no metadata
)
: Blocked, case 1
}
{
r del k
set rd
[
redis_deferring_client
]
r fsl.push k 33
$rd fsl.bpop2 k 0
r fsl.push k 34
assert_equal
{
34 33
}
[
$rd
read
]
}
test
{
Module client blocked on keys
(
no metadata
)
: Blocked, case 2
}
{
r del k
set rd
[
redis_deferring_client
]
r fsl.push k 33
r fsl.push k 34
$rd fsl.bpop2 k 0
assert_equal
{
34 33
}
[
$rd
read
]
}
test
{
Module client blocked on keys
(
with metadata
)
: No block
}
{
r del k
r fsl.push k 34
r fsl.bpopgt k 30 0
}
{
34
}
test
{
Module client blocked on keys
(
with metadata
)
: Timeout
}
{
r del k
set rd
[
redis_deferring_client
]
r fsl.push k 33
$rd fsl.bpopgt k 35 1
assert_equal
{
Request timedout
}
[
$rd
read
]
}
test
{
Module client blocked on keys
(
with metadata
)
: Blocked, case 1
}
{
r del k
set rd
[
redis_deferring_client
]
r fsl.push k 33
$rd fsl.bpopgt k 33 0
r fsl.push k 34
assert_equal
{
34
}
[
$rd
read
]
}
test
{
Module client blocked on keys
(
with metadata
)
: Blocked, case 2
}
{
r del k
set rd
[
redis_deferring_client
]
$rd fsl.bpopgt k 35 0
r fsl.push k 33
r fsl.push k 34
r fsl.push k 35
r fsl.push k 36
assert_equal
{
36
}
[
$rd
read
]
}
test
{
Module client blocked on keys does not wake up on wrong type
}
{
r del k
set rd
[
redis_deferring_client
]
$rd fsl.bpop2 k 0
r lpush k 12
r lpush k 13
r lpush k 14
r del k
r fsl.push k 33
r fsl.push k 34
assert_equal
{
34 33
}
[
$rd
read
]
}
}
tests/unit/moduleapi/hooks.tcl
View file @
0f026af1
...
@@ -3,26 +3,138 @@ set testmodule [file normalize tests/modules/hooks.so]
...
@@ -3,26 +3,138 @@ set testmodule [file normalize tests/modules/hooks.so]
tags
"modules"
{
tags
"modules"
{
start_server
{}
{
start_server
{}
{
r module load $testmodule
r module load $testmodule
r config set appendonly yes
test
{
Test clients connection / disconnection hooks
}
{
test
{
Test clients connection / disconnection hooks
}
{
for
{
set j 0
}
{
$j
< 2
}
{
incr j
}
{
for
{
set j 0
}
{
$j
< 2
}
{
incr j
}
{
set rd1
[
redis_deferring_client
]
set rd1
[
redis_deferring_client
]
$rd1 close
$rd1 close
}
}
assert
{[
r llen connected
]
> 1
}
assert
{[
r hooks.event_count client-connected
]
> 1
}
assert
{[
r llen disconnected
]
> 1
}
assert
{[
r hooks.event_count client-disconnected
]
> 1
}
}
test
{
Test module cron hook
}
{
after 100
assert
{[
r hooks.event_count cron-loop
]
> 0
}
set hz
[
r hooks.event_last cron-loop
]
assert_equal $hz 10
}
test
{
Test module loaded / unloaded hooks
}
{
set othermodule
[
file normalize tests/modules/infotest.so
]
r module load $othermodule
r module unload infotest
assert_equal
[
r hooks.event_last module-loaded
]
"infotest"
assert_equal
[
r hooks.event_last module-unloaded
]
"infotest"
}
test
{
Test module aofrw hook
}
{
r debug populate 1000 foo 10000
;
# 10mb worth of data
r config set rdbcompression no
;
# rdb progress is only checked once in 2mb
r BGREWRITEAOF
waitForBgrewriteaof r
assert_equal
[
string match
{
*module-event-persistence-aof-start*
}
[
exec tail -20 <
[
srv 0 stdout
]]]
1
assert_equal
[
string match
{
*module-event-persistence-end*
}
[
exec tail -20 <
[
srv 0 stdout
]]]
1
}
test
{
Test module aof load and rdb/aof progress hooks
}
{
# create some aof tail
(
progress is checked only once in 1000 commands
)
for
{
set j 0
}
{
$j
< 4000
}
{
incr j
}
{
r set
"bar
$j
"
x
}
# set some configs that will cause many loading progress events during aof loading
r config set key-load-delay 1
r config set dynamic-hz no
r config set hz 500
r DEBUG LOADAOF
assert_equal
[
r hooks.event_last loading-aof-start
]
0
assert_equal
[
r hooks.event_last loading-end
]
0
assert
{[
r hooks.event_count loading-rdb-start
]
== 0
}
assert
{[
r hooks.event_count loading-progress-rdb
]
>= 2
}
;
# comes from the preamble section
assert
{[
r hooks.event_count loading-progress-aof
]
>= 2
}
}
# undo configs before next test
r config set dynamic-hz yes
r config set key-load-delay 0
test
{
Test module rdb save hook
}
{
# debug reload does: save, flush, load:
assert
{[
r hooks.event_count persistence-syncrdb-start
]
== 0
}
assert
{[
r hooks.event_count loading-rdb-start
]
== 0
}
r debug reload
assert
{[
r hooks.event_count persistence-syncrdb-start
]
== 1
}
assert
{[
r hooks.event_count loading-rdb-start
]
== 1
}
}
}
test
{
Test flushdb hooks
}
{
test
{
Test flushdb hooks
}
{
r flushall
;
# Note: only the
"end"
RPUSH will survive
r select 1
r flushdb
r flushdb
r select 2
assert_equal
[
r hooks.event_last flush-start
]
9
r flushdb
assert_equal
[
r hooks.event_last flush-end
]
9
r select 9
r flushall
assert
{[
r llen flush-start
]
== 2
}
assert_equal
[
r hooks.event_last flush-start
]
-1
assert
{[
r llen flush-end
]
== 3
}
assert_equal
[
r hooks.event_last flush-end
]
-1
assert
{[
r lrange flush-start 0 -1
]
eq
{
1 2
}}
}
assert
{[
r lrange flush-end 0 -1
]
eq
{
-1 1 2
}}
# replication related tests
set master
[
srv 0 client
]
set master_host
[
srv 0 host
]
set master_port
[
srv 0 port
]
start_server
{}
{
r module load $testmodule
set replica
[
srv 0 client
]
set replica_host
[
srv 0 host
]
set replica_port
[
srv 0 port
]
$replica replicaof $master_host $master_port
wait_for_condition 50 100
{
[
string match
{
*master_link_status:up*
}
[
r info replication
]]
}
else
{
fail
"Can't turn the instance into a replica"
}
}
test
{
Test master link up hook
}
{
assert_equal
[
r hooks.event_count masterlink-up
]
1
assert_equal
[
r hooks.event_count masterlink-down
]
0
}
test
{
Test role-replica hook
}
{
assert_equal
[
r hooks.event_count role-replica
]
1
assert_equal
[
r hooks.event_count role-master
]
0
assert_equal
[
r hooks.event_last role-replica
]
[
s 0 master_host
]
}
test
{
Test replica-online hook
}
{
assert_equal
[
r -1 hooks.event_count replica-online
]
1
assert_equal
[
r -1 hooks.event_count replica-offline
]
0
}
test
{
Test master link down hook
}
{
r client kill type master
assert_equal
[
r hooks.event_count masterlink-down
]
1
}
$replica replicaof no one
test
{
Test role-master hook
}
{
assert_equal
[
r hooks.event_count role-replica
]
1
assert_equal
[
r hooks.event_count role-master
]
1
assert_equal
[
r hooks.event_last role-master
]
{}
}
test
{
Test replica-offline hook
}
{
assert_equal
[
r -1 hooks.event_count replica-online
]
1
assert_equal
[
r -1 hooks.event_count replica-offline
]
1
}
# get the replica stdout, to be used by the next test
set replica_stdout
[
srv 0 stdout
]
}
# look into the log file of the server that just exited
test
{
Test shutdown hook
}
{
assert_equal
[
string match
{
*module-event-shutdown*
}
[
exec tail -5 < $replica_stdout
]]
1
}
}
}
}
}
tests/unit/moduleapi/misc.tcl
View file @
0f026af1
...
@@ -16,4 +16,23 @@ start_server {tags {"modules"}} {
...
@@ -16,4 +16,23 @@ start_server {tags {"modules"}} {
assert
{
[
string match
"*cmdstat_module*"
$info
]
}
assert
{
[
string match
"*cmdstat_module*"
$info
]
}
}
}
test
{
test module db commands
}
{
r set x foo
set key
[
r test.randomkey
]
assert_equal $key
"x"
assert_equal
[
r test.dbsize
]
1
r test.flushall
assert_equal
[
r test.dbsize
]
0
}
test
{
test modle lru api
}
{
r set x foo
set lru
[
r test.getlru x
]
assert
{
$lru <= 1
}
r test.setlru x 100
set idle
[
r object idletime x
]
assert
{
$idle >= 100
}
set lru
[
r test.getlru x
]
assert
{
$lru >= 100
}
}
}
}
tests/unit/type/stream.tcl
View file @
0f026af1
...
@@ -79,6 +79,12 @@ start_server {
...
@@ -79,6 +79,12 @@ start_server {
assert
{[
streamCompareID $id2 $id3
]
== -1
}
assert
{[
streamCompareID $id2 $id3
]
== -1
}
}
}
test
{
XADD IDs correctly report an error when overflowing
}
{
r DEL mystream
r xadd mystream 18446744073709551615-18446744073709551615 a b
assert_error ERR*
{
r xadd mystream * c d
}
}
test
{
XADD with MAXLEN option
}
{
test
{
XADD with MAXLEN option
}
{
r DEL mystream
r DEL mystream
for
{
set j 0
}
{
$j
< 1000
}
{
incr j
}
{
for
{
set j 0
}
{
$j
< 1000
}
{
incr j
}
{
...
...
Prev
1
2
Next
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