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
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