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
d375595d
Unverified
Commit
d375595d
authored
Apr 27, 2022
by
Oran Agra
Committed by
GitHub
Apr 27, 2022
Browse files
Merge pull request #10652 from oranagra/redis-7.0.0
Redis 7.0.0
parents
fb4e0d40
c1f30206
Changes
124
Show whitespace changes
Inline
Side-by-side
tests/modules/basics.c
View file @
d375595d
...
...
@@ -866,10 +866,10 @@ int TestBasics(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if
(
!
TestAssertStringReply
(
ctx
,
RedisModule_CallReplyArrayElement
(
reply
,
1
),
"1234"
,
4
))
goto
fail
;
T
(
"foo"
,
"E"
);
if
(
!
TestAssertErrorReply
(
ctx
,
reply
,
"ERR
U
nknown
Redis
command 'foo'
."
,
32
))
goto
fail
;
if
(
!
TestAssertErrorReply
(
ctx
,
reply
,
"ERR
u
nknown command 'foo'
, with args beginning with: "
,
53
))
goto
fail
;
T
(
"set"
,
"Ec"
,
"x"
);
if
(
!
TestAssertErrorReply
(
ctx
,
reply
,
"ERR
W
rong number of arg
s calling Redis command 'set'."
,
53
))
goto
fail
;
if
(
!
TestAssertErrorReply
(
ctx
,
reply
,
"ERR
w
rong number of arg
uments for 'set' command"
,
47
))
goto
fail
;
T
(
"shutdown"
,
"SE"
);
if
(
!
TestAssertErrorReply
(
ctx
,
reply
,
"ERR command 'shutdown' is not allowed on script mode"
,
52
))
goto
fail
;
...
...
tests/modules/keyspace_events.c
View file @
d375595d
...
...
@@ -79,6 +79,17 @@ static int KeySpace_NotificationGeneric(RedisModuleCtx *ctx, int type, const cha
return
REDISMODULE_OK
;
}
static
int
KeySpace_NotificationExpired
(
RedisModuleCtx
*
ctx
,
int
type
,
const
char
*
event
,
RedisModuleString
*
key
)
{
REDISMODULE_NOT_USED
(
type
);
REDISMODULE_NOT_USED
(
event
);
REDISMODULE_NOT_USED
(
key
);
RedisModuleCallReply
*
rep
=
RedisModule_Call
(
ctx
,
"INCR"
,
"c!"
,
"testkeyspace:expired"
);
RedisModule_FreeCallReply
(
rep
);
return
REDISMODULE_OK
;
}
static
int
KeySpace_NotificationModule
(
RedisModuleCtx
*
ctx
,
int
type
,
const
char
*
event
,
RedisModuleString
*
key
)
{
REDISMODULE_NOT_USED
(
ctx
);
REDISMODULE_NOT_USED
(
type
);
...
...
@@ -233,6 +244,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
return
REDISMODULE_ERR
;
}
if
(
RedisModule_SubscribeToKeyspaceEvents
(
ctx
,
REDISMODULE_NOTIFY_EXPIRED
,
KeySpace_NotificationExpired
)
!=
REDISMODULE_OK
){
return
REDISMODULE_ERR
;
}
if
(
RedisModule_SubscribeToKeyspaceEvents
(
ctx
,
REDISMODULE_NOTIFY_MODULE
,
KeySpace_NotificationModule
)
!=
REDISMODULE_OK
){
return
REDISMODULE_ERR
;
}
...
...
tests/modules/mallocsize.c
0 → 100644
View file @
d375595d
#include "redismodule.h"
#include <string.h>
#include <assert.h>
#include <unistd.h>
#define UNUSED(V) ((void) V)
/* Registered type */
RedisModuleType
*
mallocsize_type
=
NULL
;
typedef
enum
{
UDT_RAW
,
UDT_STRING
,
UDT_DICT
}
udt_type_t
;
typedef
struct
{
void
*
ptr
;
size_t
len
;
}
raw_t
;
typedef
struct
{
udt_type_t
type
;
union
{
raw_t
raw
;
RedisModuleString
*
str
;
RedisModuleDict
*
dict
;
}
data
;
}
udt_t
;
void
udt_free
(
void
*
value
)
{
udt_t
*
udt
=
value
;
switch
(
udt
->
type
)
{
case
(
UDT_RAW
):
{
RedisModule_Free
(
udt
->
data
.
raw
.
ptr
);
break
;
}
case
(
UDT_STRING
):
{
RedisModule_FreeString
(
NULL
,
udt
->
data
.
str
);
break
;
}
case
(
UDT_DICT
):
{
RedisModuleString
*
dk
,
*
dv
;
RedisModuleDictIter
*
iter
=
RedisModule_DictIteratorStartC
(
udt
->
data
.
dict
,
"^"
,
NULL
,
0
);
while
((
dk
=
RedisModule_DictNext
(
NULL
,
iter
,
(
void
**
)
&
dv
))
!=
NULL
)
{
RedisModule_FreeString
(
NULL
,
dk
);
RedisModule_FreeString
(
NULL
,
dv
);
}
RedisModule_DictIteratorStop
(
iter
);
RedisModule_FreeDict
(
NULL
,
udt
->
data
.
dict
);
break
;
}
}
RedisModule_Free
(
udt
);
}
void
udt_rdb_save
(
RedisModuleIO
*
rdb
,
void
*
value
)
{
udt_t
*
udt
=
value
;
RedisModule_SaveUnsigned
(
rdb
,
udt
->
type
);
switch
(
udt
->
type
)
{
case
(
UDT_RAW
):
{
RedisModule_SaveStringBuffer
(
rdb
,
udt
->
data
.
raw
.
ptr
,
udt
->
data
.
raw
.
len
);
break
;
}
case
(
UDT_STRING
):
{
RedisModule_SaveString
(
rdb
,
udt
->
data
.
str
);
break
;
}
case
(
UDT_DICT
):
{
RedisModule_SaveUnsigned
(
rdb
,
RedisModule_DictSize
(
udt
->
data
.
dict
));
RedisModuleString
*
dk
,
*
dv
;
RedisModuleDictIter
*
iter
=
RedisModule_DictIteratorStartC
(
udt
->
data
.
dict
,
"^"
,
NULL
,
0
);
while
((
dk
=
RedisModule_DictNext
(
NULL
,
iter
,
(
void
**
)
&
dv
))
!=
NULL
)
{
RedisModule_SaveString
(
rdb
,
dk
);
RedisModule_SaveString
(
rdb
,
dv
);
RedisModule_FreeString
(
NULL
,
dk
);
/* Allocated by RedisModule_DictNext */
}
RedisModule_DictIteratorStop
(
iter
);
break
;
}
}
}
void
*
udt_rdb_load
(
RedisModuleIO
*
rdb
,
int
encver
)
{
if
(
encver
!=
0
)
return
NULL
;
udt_t
*
udt
=
RedisModule_Alloc
(
sizeof
(
*
udt
));
udt
->
type
=
RedisModule_LoadUnsigned
(
rdb
);
switch
(
udt
->
type
)
{
case
(
UDT_RAW
):
{
udt
->
data
.
raw
.
ptr
=
RedisModule_LoadStringBuffer
(
rdb
,
&
udt
->
data
.
raw
.
len
);
break
;
}
case
(
UDT_STRING
):
{
udt
->
data
.
str
=
RedisModule_LoadString
(
rdb
);
break
;
}
case
(
UDT_DICT
):
{
long
long
dict_len
=
RedisModule_LoadUnsigned
(
rdb
);
udt
->
data
.
dict
=
RedisModule_CreateDict
(
NULL
);
for
(
int
i
=
0
;
i
<
dict_len
;
i
+=
2
)
{
RedisModuleString
*
key
=
RedisModule_LoadString
(
rdb
);
RedisModuleString
*
val
=
RedisModule_LoadString
(
rdb
);
RedisModule_DictSet
(
udt
->
data
.
dict
,
key
,
val
);
}
break
;
}
}
return
udt
;
}
size_t
udt_mem_usage
(
RedisModuleKeyOptCtx
*
ctx
,
const
void
*
value
,
size_t
sample_size
)
{
UNUSED
(
ctx
);
UNUSED
(
sample_size
);
const
udt_t
*
udt
=
value
;
size_t
size
=
sizeof
(
*
udt
);
switch
(
udt
->
type
)
{
case
(
UDT_RAW
):
{
size
+=
RedisModule_MallocSize
(
udt
->
data
.
raw
.
ptr
);
break
;
}
case
(
UDT_STRING
):
{
size
+=
RedisModule_MallocSizeString
(
udt
->
data
.
str
);
break
;
}
case
(
UDT_DICT
):
{
void
*
dk
;
size_t
keylen
;
RedisModuleString
*
dv
;
RedisModuleDictIter
*
iter
=
RedisModule_DictIteratorStartC
(
udt
->
data
.
dict
,
"^"
,
NULL
,
0
);
while
((
dk
=
RedisModule_DictNextC
(
iter
,
&
keylen
,
(
void
**
)
&
dv
))
!=
NULL
)
{
size
+=
keylen
;
size
+=
RedisModule_MallocSizeString
(
dv
);
}
RedisModule_DictIteratorStop
(
iter
);
break
;
}
}
return
size
;
}
/* MALLOCSIZE.SETRAW key len */
int
cmd_setraw
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
if
(
argc
!=
3
)
return
RedisModule_WrongArity
(
ctx
);
RedisModuleKey
*
key
=
RedisModule_OpenKey
(
ctx
,
argv
[
1
],
REDISMODULE_WRITE
);
udt_t
*
udt
=
RedisModule_Alloc
(
sizeof
(
*
udt
));
udt
->
type
=
UDT_RAW
;
long
long
raw_len
;
RedisModule_StringToLongLong
(
argv
[
2
],
&
raw_len
);
udt
->
data
.
raw
.
ptr
=
RedisModule_Alloc
(
raw_len
);
udt
->
data
.
raw
.
len
=
raw_len
;
RedisModule_ModuleTypeSetValue
(
key
,
mallocsize_type
,
udt
);
RedisModule_CloseKey
(
key
);
return
RedisModule_ReplyWithSimpleString
(
ctx
,
"OK"
);
}
/* MALLOCSIZE.SETSTR key string */
int
cmd_setstr
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
if
(
argc
!=
3
)
return
RedisModule_WrongArity
(
ctx
);
RedisModuleKey
*
key
=
RedisModule_OpenKey
(
ctx
,
argv
[
1
],
REDISMODULE_WRITE
);
udt_t
*
udt
=
RedisModule_Alloc
(
sizeof
(
*
udt
));
udt
->
type
=
UDT_STRING
;
udt
->
data
.
str
=
argv
[
2
];
RedisModule_RetainString
(
ctx
,
argv
[
2
]);
RedisModule_ModuleTypeSetValue
(
key
,
mallocsize_type
,
udt
);
RedisModule_CloseKey
(
key
);
return
RedisModule_ReplyWithSimpleString
(
ctx
,
"OK"
);
}
/* MALLOCSIZE.SETDICT key field value [field value ...] */
int
cmd_setdict
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
if
(
argc
<
4
||
argc
%
2
)
return
RedisModule_WrongArity
(
ctx
);
RedisModuleKey
*
key
=
RedisModule_OpenKey
(
ctx
,
argv
[
1
],
REDISMODULE_WRITE
);
udt_t
*
udt
=
RedisModule_Alloc
(
sizeof
(
*
udt
));
udt
->
type
=
UDT_DICT
;
udt
->
data
.
dict
=
RedisModule_CreateDict
(
ctx
);
for
(
int
i
=
2
;
i
<
argc
;
i
+=
2
)
{
RedisModule_DictSet
(
udt
->
data
.
dict
,
argv
[
i
],
argv
[
i
+
1
]);
/* No need to retain argv[i], it is copied as the rax key */
RedisModule_RetainString
(
ctx
,
argv
[
i
+
1
]);
}
RedisModule_ModuleTypeSetValue
(
key
,
mallocsize_type
,
udt
);
RedisModule_CloseKey
(
key
);
return
RedisModule_ReplyWithSimpleString
(
ctx
,
"OK"
);
}
int
RedisModule_OnLoad
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
UNUSED
(
argv
);
UNUSED
(
argc
);
if
(
RedisModule_Init
(
ctx
,
"mallocsize"
,
1
,
REDISMODULE_APIVER_1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
RedisModuleTypeMethods
tm
=
{
.
version
=
REDISMODULE_TYPE_METHOD_VERSION
,
.
rdb_load
=
udt_rdb_load
,
.
rdb_save
=
udt_rdb_save
,
.
free
=
udt_free
,
.
mem_usage2
=
udt_mem_usage
,
};
mallocsize_type
=
RedisModule_CreateDataType
(
ctx
,
"allocsize"
,
0
,
&
tm
);
if
(
mallocsize_type
==
NULL
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"mallocsize.setraw"
,
cmd_setraw
,
""
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"mallocsize.setstr"
,
cmd_setstr
,
""
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"mallocsize.setdict"
,
cmd_setdict
,
""
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
return
REDISMODULE_OK
;
}
tests/modules/moduleconfigs.c
View file @
d375595d
...
...
@@ -6,6 +6,7 @@ long long longval;
long
long
memval
;
RedisModuleString
*
strval
=
NULL
;
int
enumval
;
int
flagsval
;
/* Series of get and set callbacks for each type of config, these rely on the privdata ptr
* to point to the config, and they register the configs as such. Note that one could also just
...
...
@@ -68,6 +69,20 @@ int setEnumConfigCommand(const char *name, int val, void *privdata, RedisModuleS
return
REDISMODULE_OK
;
}
int
getFlagsConfigCommand
(
const
char
*
name
,
void
*
privdata
)
{
REDISMODULE_NOT_USED
(
name
);
REDISMODULE_NOT_USED
(
privdata
);
return
flagsval
;
}
int
setFlagsConfigCommand
(
const
char
*
name
,
int
val
,
void
*
privdata
,
RedisModuleString
**
err
)
{
REDISMODULE_NOT_USED
(
name
);
REDISMODULE_NOT_USED
(
err
);
REDISMODULE_NOT_USED
(
privdata
);
flagsval
=
val
;
return
REDISMODULE_OK
;
}
int
boolApplyFunc
(
RedisModuleCtx
*
ctx
,
void
*
privdata
,
RedisModuleString
**
err
)
{
REDISMODULE_NOT_USED
(
ctx
);
REDISMODULE_NOT_USED
(
privdata
);
...
...
@@ -106,10 +121,13 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
}
/* On the stack to make sure we're copying them. */
const
char
*
enum_vals
[
3
]
=
{
"one"
,
"two"
,
"three"
};
const
int
int_vals
[
3
]
=
{
0
,
2
,
4
};
const
char
*
enum_vals
[]
=
{
"none"
,
"one"
,
"two"
,
"three"
};
const
int
int_vals
[]
=
{
0
,
1
,
2
,
4
};
if
(
RedisModule_RegisterEnumConfig
(
ctx
,
"enum"
,
0
,
REDISMODULE_CONFIG_DEFAULT
,
enum_vals
,
int_vals
,
3
,
getEnumConfigCommand
,
setEnumConfigCommand
,
NULL
,
NULL
)
==
REDISMODULE_ERR
)
{
if
(
RedisModule_RegisterEnumConfig
(
ctx
,
"enum"
,
1
,
REDISMODULE_CONFIG_DEFAULT
,
enum_vals
,
int_vals
,
4
,
getEnumConfigCommand
,
setEnumConfigCommand
,
NULL
,
NULL
)
==
REDISMODULE_ERR
)
{
return
REDISMODULE_ERR
;
}
if
(
RedisModule_RegisterEnumConfig
(
ctx
,
"flags"
,
3
,
REDISMODULE_CONFIG_DEFAULT
|
REDISMODULE_CONFIG_BITFLAGS
,
enum_vals
,
int_vals
,
4
,
getFlagsConfigCommand
,
setFlagsConfigCommand
,
NULL
,
NULL
)
==
REDISMODULE_ERR
)
{
return
REDISMODULE_ERR
;
}
/* Memory config here. */
...
...
tests/modules/publish.c
0 → 100644
View file @
d375595d
#include "redismodule.h"
#include <string.h>
#include <assert.h>
#include <unistd.h>
#define UNUSED(V) ((void) V)
int
cmd_publish_classic
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
if
(
argc
!=
3
)
return
RedisModule_WrongArity
(
ctx
);
int
receivers
=
RedisModule_PublishMessage
(
ctx
,
argv
[
1
],
argv
[
2
]);
RedisModule_ReplyWithLongLong
(
ctx
,
receivers
);
return
REDISMODULE_OK
;
}
int
cmd_publish_shard
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
if
(
argc
!=
3
)
return
RedisModule_WrongArity
(
ctx
);
int
receivers
=
RedisModule_PublishMessageShard
(
ctx
,
argv
[
1
],
argv
[
2
]);
RedisModule_ReplyWithLongLong
(
ctx
,
receivers
);
return
REDISMODULE_OK
;
}
int
RedisModule_OnLoad
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
UNUSED
(
argv
);
UNUSED
(
argc
);
if
(
RedisModule_Init
(
ctx
,
"publish"
,
1
,
REDISMODULE_APIVER_1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"publish.classic"
,
cmd_publish_classic
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"publish.shard"
,
cmd_publish_shard
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
return
REDISMODULE_OK
;
}
tests/modules/subcommands.c
View file @
d375595d
...
...
@@ -11,7 +11,10 @@ int cmd_set(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
int
cmd_get
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
UNUSED
(
argv
);
UNUSED
(
argc
);
if
(
argc
>
4
)
/* For testing */
return
RedisModule_WrongArity
(
ctx
);
RedisModule_ReplyWithSimpleString
(
ctx
,
"OK"
);
return
REDISMODULE_OK
;
}
...
...
tests/sentinel/tests/05-manual.tcl
View file @
d375595d
...
...
@@ -3,9 +3,9 @@
source
"../tests/includes/init-tests.tcl"
foreach_sentinel_id id
{
S $id sentinel debug info-period
1
000
S $id sentinel debug default-down-after
3
000
S $id sentinel debug publish-period
5
00
S $id sentinel debug info-period
2
000
S $id sentinel debug default-down-after
6
000
S $id sentinel debug publish-period
10
00
}
test
"Manual failover works"
{
...
...
tests/sentinel/tests/includes/init-tests.tcl
View file @
d375595d
...
...
@@ -28,7 +28,8 @@ test "(init) Sentinels can start monitoring a master" {
foreach_sentinel_id id
{
assert
{[
S $id sentinel master mymaster
]
ne
{}}
S $id SENTINEL SET mymaster down-after-milliseconds 2000
S $id SENTINEL SET mymaster failover-timeout 20000
S $id SENTINEL SET mymaster failover-timeout 10000
S $id SENTINEL debug tilt-period 5000
S $id SENTINEL SET mymaster parallel-syncs 10
if
{
$::leaked
_fds_file !=
""
&&
[
exec uname
]
==
"Linux"
}
{
S $id SENTINEL SET mymaster notification-script ../../tests/helpers/check_leaked_fds.tcl
...
...
tests/support/util.tcl
View file @
d375595d
...
...
@@ -77,6 +77,12 @@ proc getInfoProperty {infostr property} {
}
}
proc cluster_info
{
r field
}
{
if
{[
regexp
"^
$field:
(.*?)
\r\n
"
[
$r
cluster info
]
_ value
]}
{
set _ $value
}
}
# Return value for INFO property
proc status
{
r property
}
{
set _
[
getInfoProperty
[
{*}
$r
info
]
$property
]
...
...
@@ -823,11 +829,21 @@ proc subscribe {client channels} {
consume_subscribe_messages $client subscribe $channels
}
proc ssubscribe
{
client channels
}
{
$client ssubscribe
{*}
$channels
consume_subscribe_messages $client ssubscribe $channels
}
proc unsubscribe
{
client
{
channels
{}}}
{
$client unsubscribe
{*}
$channels
consume_subscribe_messages $client unsubscribe $channels
}
proc sunsubscribe
{
client
{
channels
{}}}
{
$client sunsubscribe
{*}
$channels
consume_subscribe_messages $client sunsubscribe $channels
}
proc psubscribe
{
client channels
}
{
$client psubscribe
{*}
$channels
consume_subscribe_messages $client psubscribe $channels
...
...
tests/test_helper.tcl
View file @
d375595d
...
...
@@ -94,6 +94,7 @@ set ::all_tests {
unit/client-eviction
unit/violations
unit/replybufsize
unit/cluster-scripting
}
# Index to the next test to run in the ::all_tests list.
set ::next_test 0
...
...
@@ -274,6 +275,16 @@ proc s {args} {
status
[
srv $level
"client"
]
[
lindex $args 0
]
}
# Provide easy access to CLUSTER INFO properties. Same semantic as
"proc s"
.
proc csi
{
args
}
{
set level 0
if
{[
string is integer
[
lindex $args 0
]]}
{
set level
[
lindex $args 0
]
set args
[
lrange $args 1 end
]
}
cluster_info
[
srv $level
"client"
]
[
lindex $args 0
]
}
# Test wrapped into run_solo are sent back from the client to the
# test server, so that the test server will send them again to
# clients once the clients are idle.
...
...
tests/unit/acl-v2.tcl
View file @
d375595d
...
...
@@ -173,7 +173,7 @@ start_server {tags {"acl external:skip"}} {
assert_equal PONG
[
$r2
PING
]
assert_equal
{}
[
$r2
get readwrite_str
]
assert_error
{
ERR* not an integer *
}
{
$r2
set readwrite_str bar ex get
}
assert_error
{
ERR
* not an integer *
}
{
$r2
set readwrite_str bar ex get
}
assert_equal
{
OK
}
[
$r2
set readwrite_str bar
]
assert_equal
{
bar
}
[
$r2
get readwrite_str
]
...
...
tests/unit/acl.tcl
View file @
d375595d
...
...
@@ -511,7 +511,7 @@ start_server {tags {"acl external:skip"}} {
test
"ACL CAT with illegal arguments"
{
assert_error
{
*Unknown category 'NON_EXISTS'
}
{
r ACL CAT NON_EXISTS
}
assert_error
{
*
U
nknown subcommand or wrong number of arguments for 'CAT'*
}
{
r ACL CAT NON_EXISTS NON_EXISTS2
}
assert_error
{
*
u
nknown subcommand or wrong number of arguments for 'CAT'*
}
{
r ACL CAT NON_EXISTS NON_EXISTS2
}
}
test
"ACL CAT without category - list all categories"
{
...
...
tests/unit/auth.tcl
View file @
d375595d
...
...
@@ -2,7 +2,7 @@ start_server {tags {"auth external:skip"}} {
test
{
AUTH fails if there is no password configured server side
}
{
catch
{
r auth foo
}
err
set _ $err
}
{
ERR*any password*
}
}
{
ERR
*any password*
}
test
{
Arity check for auth command
}
{
catch
{
r auth a b c
}
err
...
...
tests/unit/bitops.tcl
View file @
d375595d
...
...
@@ -133,12 +133,12 @@ start_server {tags {"bitops"}} {
test
{
BITCOUNT syntax error #1
}
{
catch
{
r bitcount s 0
}
e
set e
}
{
ERR*syntax*
}
}
{
ERR
*syntax*
}
test
{
BITCOUNT syntax error #2
}
{
catch
{
r bitcount s 0 1 hello
}
e
set e
}
{
ERR*syntax*
}
}
{
ERR
*syntax*
}
test
{
BITCOUNT regression test for github issue #582
}
{
r del foo
...
...
@@ -546,7 +546,10 @@ start_server {tags {"bitops"}} {
}
}
}
}
run_solo
{
bitops-large-memory
}
{
start_server
{
tags
{
"bitops"
}}
{
test
"BIT pos larger than UINT_MAX"
{
set bytes
[
expr
(
1 << 29
)
+ 1
]
set bitpos
[
expr
(
1 << 32
)]
...
...
@@ -587,3 +590,4 @@ start_server {tags {"bitops"}} {
r del mykey
}
{
1
}
{
large-memory needs:debug
}
}
}
;
#run_solo
tests/unit/cluster-scripting.tcl
0 → 100644
View file @
d375595d
# make sure the test infra won't use SELECT
set old_singledb $::singledb
set ::singledb 1
start_server
{
overrides
{
cluster-enabled yes
}
tags
{
external:skip cluster
}}
{
r 0 cluster addslotsrange 0 16383
wait_for_condition 50 100
{
[
csi 0 cluster_state
]
eq
"ok"
}
else
{
fail
"Cluster never became 'ok'"
}
test
{
Eval scripts with shebangs and functions default to no cross slots
}
{
# Test that scripts with shebang block cross slot operations
assert_error
"ERR Script attempted to access keys that do not hash to the same slot*"
{
r 0 eval
{
#!lua
redis.call
(
'set', 'foo', 'bar'
)
redis.call
(
'set', 'bar', 'foo'
)
return 'OK'
}
0
}
# Test the functions by default block cross slot operations
r 0 function load REPLACE
{
#!lua name=crossslot
local function test_cross_slot
(
keys, args
)
redis.call
(
'set', 'foo', 'bar'
)
redis.call
(
'set', 'bar', 'foo'
)
return 'OK'
end
redis.register_function
(
'test_cross_slot', test_cross_slot
)}
assert_error
"ERR Script attempted to access keys that do not hash to the same slot*"
{
r FCALL test_cross_slot 0
}
}
test
{
Cross slot commands are allowed by default for eval scripts and with allow-cross-slot-keys flag
}
{
# Old style lua scripts are allowed to access cross slot operations
r 0 eval
"redis.call('set', 'foo', 'bar'); redis.call('set', 'bar', 'foo')"
0
# scripts with allow-cross-slot-keys flag are allowed
r 0 eval
{
#!lua flags=allow-cross-slot-keys
redis.call
(
'set', 'foo', 'bar'
);
redis.call
(
'set', 'bar', 'foo'
)
}
0
# Functions with allow-cross-slot-keys flag are allowed
r 0 function load REPLACE
{
#!lua name=crossslot
local function test_cross_slot
(
keys, args
)
redis.call
(
'set', 'foo', 'bar'
)
redis.call
(
'set', 'bar', 'foo'
)
return 'OK'
end
redis.register_function
{
function_name='test_cross_slot', callback=test_cross_slot, flags=
{
'allow-cross-slot-keys'
}}}
r FCALL test_cross_slot 0
}
test
{
Cross slot commands are also blocked if they disagree with pre-declared keys
}
{
assert_error
"ERR Script attempted to access keys that do not hash to the same slot*"
{
r 0 eval
{
#!lua
redis.call
(
'set', 'foo', 'bar'
)
return 'OK'
}
1 bar
}
}
}
set ::singledb $old_singledb
tests/unit/functions.tcl
View file @
d375595d
...
...
@@ -117,7 +117,7 @@ start_server {tags {"scripting"}} {
r function bad_subcommand
}
e
set _ $e
}
{
*
U
nknown subcommand*
}
}
{
*
u
nknown subcommand*
}
test
{
FUNCTION - test loading from rdb
}
{
r debug reload
...
...
@@ -205,7 +205,7 @@ start_server {tags {"scripting"}} {
test
{
FUNCTION - test function restore with wrong number of arguments
}
{
catch
{
r function restore arg1 args2 arg3
}
e
set _ $e
}
{
*
U
nknown subcommand or wrong number of arguments for 'restore'. Try FUNCTION HELP.
}
}
{
*
u
nknown subcommand or wrong number of arguments for 'restore'. Try FUNCTION HELP.
}
test
{
FUNCTION - test fcall_ro with write command
}
{
r function load REPLACE
[
get_no_writes_function_code lua test test
{
return redis.call
(
'set', 'x', '1'
)}]
...
...
@@ -298,7 +298,7 @@ start_server {tags {"scripting"}} {
assert_match
{
*only supports SYNC|ASYNC*
}
$e
catch
{
r function flush sync extra_arg
}
e
assert_match
{
*
U
nknown subcommand or wrong number of arguments for 'flush'. Try FUNCTION HELP.
}
$e
assert_match
{
*
u
nknown subcommand or wrong number of arguments for 'flush'. Try FUNCTION HELP.
}
$e
}
}
...
...
@@ -624,16 +624,16 @@ start_server {tags {"scripting"}} {
}
}
e
set _ $e
}
{
*attempt to
call field 'call'
(
a nil value
)
*
}
}
{
*attempt
ed
to
access nonexistent global variable 'call'
*
}
test
{
LIBRARIES - redis.
call
from function load
}
{
test
{
LIBRARIES - redis.
setresp
from function load
}
{
catch
{
r function load replace
{
#!lua name=lib2
return redis.setresp
(
3
)
}
}
e
set _ $e
}
{
*attempt to
call field 'setresp'
(
a nil value
)
*
}
}
{
*attempt
ed
to
access nonexistent global variable 'setresp'
*
}
test
{
LIBRARIES - redis.set_repl from function load
}
{
catch
{
...
...
@@ -642,7 +642,7 @@ start_server {tags {"scripting"}} {
}
}
e
set _ $e
}
{
*attempt to
call field 'set_repl'
(
a nil value
)
*
}
}
{
*attempt
ed
to
access nonexistent global variable 'set_repl'
*
}
test
{
LIBRARIES - malicious access test
}
{
# the 'library' API is not exposed inside a
...
...
@@ -669,37 +669,18 @@ start_server {tags {"scripting"}} {
end
)
end
)
}
assert_equal
{
OK
}
[
r fcall f1 0
]
catch
{[
r fcall f1 0
]}
e
assert_match
{
*Attempt to modify a readonly table*
}
$e
catch
{[
r function load
{
#!lua name=lib2
redis.math.random
()
}]}
e
assert_match
{
*can only be called inside a script invocation*
}
$e
catch
{[
r function load
{
#!lua name=lib2
redis.math.randomseed
()
}]}
e
assert_match
{
*can only be called inside a script invocation*
}
$e
assert_match
{
*Script attempted to access nonexistent global variable 'math'*
}
$e
catch
{[
r function load
{
#!lua name=lib2
redis.redis.call
(
'ping'
)
}]}
e
assert_match
{
*can only be called inside a script invocation*
}
$e
catch
{[
r function load
{
#!lua name=lib2
redis.redis.pcall
(
'ping'
)
}]}
e
assert_match
{
*can only be called inside a script invocation*
}
$e
catch
{[
r function load
{
#!lua name=lib2
redis.redis.setresp
(
3
)
}]}
e
assert_match
{
*can only be called inside a script invocation*
}
$e
catch
{[
r function load
{
#!lua name=lib2
redis.redis.set_repl
(
redis.redis.REPL_NONE
)
}]}
e
assert_match
{
*can only be called inside a script invocation*
}
$e
assert_match
{
*Script attempted to access nonexistent global variable 'redis'*
}
$e
catch
{[
r fcall f2 0
]}
e
assert_match
{
*can only be called on FUNCTION LOAD command*
}
$e
...
...
@@ -756,7 +737,7 @@ start_server {tags {"scripting"}} {
}
}
e
set _ $e
}
{
*
a
ttempt
ed
to
create global variable 'a'
*
}
}
{
*
A
ttempt to
modify a readonly table
*
}
test
{
LIBRARIES - named arguments
}
{
r function load
{
#!lua name=lib
...
...
@@ -986,7 +967,7 @@ start_server {tags {"scripting"}} {
assert_match
{
*command not allowed when used memory*
}
$e
r config set maxmemory 0
}
}
{
OK
}
{
needs:config-maxmemory
}
test
{
FUNCTION - verify allow-omm allows running any command
}
{
r FUNCTION load replace
{
#!lua name=f1
...
...
@@ -999,11 +980,11 @@ start_server {tags {"scripting"}} {
r config set maxmemory 1
assert_match
{
OK
}
[
r fcall f1 1
k
]
assert_match
{
OK
}
[
r fcall f1 1
x
]
assert_match
{
1
}
[
r get x
]
r config set maxmemory 0
}
}
{
OK
}
{
needs:config-maxmemory
}
}
start_server
{
tags
{
"scripting"
}}
{
...
...
@@ -1074,7 +1055,7 @@ start_server {tags {"scripting"}} {
assert_match
{
*can not run it when used memory > 'maxmemory'*
}
$e
r config set maxmemory 0
}
}
{
OK
}
{
needs:config-maxmemory
}
test
{
FUNCTION - deny oom on no-writes function
}
{
r FUNCTION load replace
{
#!lua name=test
...
...
@@ -1090,7 +1071,7 @@ start_server {tags {"scripting"}} {
assert_match
{
*can not run it when used memory > 'maxmemory'*
}
$e
r config set maxmemory 0
}
}
{
OK
}
{
needs:config-maxmemory
}
test
{
FUNCTION - allow stale
}
{
r FUNCTION load replace
{
#!lua name=test
...
...
@@ -1198,4 +1179,32 @@ start_server {tags {"scripting"}} {
redis.register_function
(
'foo', function
()
return 1 end
)
}
}
{
foo
}
test
{
FUNCTION - trick global protection 1
}
{
r FUNCTION FLUSH
r FUNCTION load
{
#!lua name=test1
redis.register_function
(
'f1', function
()
mt = getmetatable
(
_G
)
original_globals = mt.__index
original_globals
[
'redis'
]
= function
()
return 1 end
end
)
}
catch
{[
r fcall f1 0
]}
e
set _ $e
}
{
*Attempt to modify a readonly table*
}
test
{
FUNCTION - test getmetatable on script load
}
{
r FUNCTION FLUSH
catch
{
r FUNCTION load
{
#!lua name=test1
mt = getmetatable
(
_G
)
}
}
e
set _ $e
}
{
*Script attempted to access nonexistent global variable 'getmetatable'*
}
}
tests/unit/geo.tcl
View file @
d375595d
...
...
@@ -193,14 +193,14 @@ start_server {tags {"geo"}} {
r geoadd nyc xx nx -73.9454966 40.747533
"lic market"
}
err
set err
}
{
ERR*syntax*
}
}
{
ERR
*syntax*
}
test
{
GEOADD update with invalid option
}
{
catch
{
r geoadd nyc ch xx foo -73.9454966 40.747533
"lic market"
}
err
set err
}
{
ERR*syntax*
}
}
{
ERR
*syntax*
}
test
{
GEOADD invalid coordinates
}
{
catch
{
...
...
@@ -229,27 +229,27 @@ start_server {tags {"geo"}} {
test
{
GEOSEARCH FROMLONLAT and FROMMEMBER cannot exist at the same time
}
{
catch
{
r geosearch nyc fromlonlat -73.9798091 40.7598464 frommember xxx bybox 6 6 km asc
}
e
set e
}
{
ERR*syntax*
}
}
{
ERR
*syntax*
}
test
{
GEOSEARCH FROMLONLAT and FROMMEMBER one must exist
}
{
catch
{
r geosearch nyc bybox 3 3 km asc desc withhash withdist withcoord
}
e
set e
}
{
ERR*exactly one of FROMMEMBER or FROMLONLAT*
}
}
{
ERR
*exactly one of FROMMEMBER or FROMLONLAT*
}
test
{
GEOSEARCH BYRADIUS and BYBOX cannot exist at the same time
}
{
catch
{
r geosearch nyc fromlonlat -73.9798091 40.7598464 byradius 3 km bybox 3 3 km asc
}
e
set e
}
{
ERR*syntax*
}
}
{
ERR
*syntax*
}
test
{
GEOSEARCH BYRADIUS and BYBOX one must exist
}
{
catch
{
r geosearch nyc fromlonlat -73.9798091 40.7598464 asc desc withhash withdist withcoord
}
e
set e
}
{
ERR*exactly one of BYRADIUS and BYBOX*
}
}
{
ERR
*exactly one of BYRADIUS and BYBOX*
}
test
{
GEOSEARCH with STOREDIST option
}
{
catch
{
r geosearch nyc fromlonlat -73.9798091 40.7598464 bybox 6 6 km asc storedist
}
e
set e
}
{
ERR*syntax*
}
}
{
ERR
*syntax*
}
test
{
GEORADIUS withdist
(
sorted
)}
{
r georadius nyc -73.9798091 40.7598464 3 km withdist asc
...
...
@@ -274,12 +274,12 @@ start_server {tags {"geo"}} {
test
{
GEORADIUS with ANY but no COUNT
}
{
catch
{
r georadius nyc -73.9798091 40.7598464 10 km ANY ASC
}
e
set e
}
{
ERR*ANY*requires*COUNT*
}
}
{
ERR
*ANY*requires*COUNT*
}
test
{
GEORADIUS with COUNT but missing integer argument
}
{
catch
{
r georadius nyc -73.9798091 40.7598464 10 km COUNT
}
e
set e
}
{
ERR*syntax*
}
}
{
ERR
*syntax*
}
test
{
GEORADIUS with COUNT DESC
}
{
r georadius nyc -73.9798091 40.7598464 10 km COUNT 2 DESC
...
...
tests/unit/introspection.tcl
View file @
d375595d
...
...
@@ -23,9 +23,9 @@ start_server {tags {"introspection"}} {
assert_error
"ERR wrong number of arguments for 'client|kill' command"
{
r client kill
}
assert_error
"ERR syntax error*"
{
r client kill id 10 wrong_arg
}
assert_error
"ERR*greater than 0*"
{
r client kill id str
}
assert_error
"ERR*greater than 0*"
{
r client kill id -1
}
assert_error
"ERR*greater than 0*"
{
r client kill id 0
}
assert_error
"ERR
*greater than 0*"
{
r client kill id str
}
assert_error
"ERR
*greater than 0*"
{
r client kill id -1
}
assert_error
"ERR
*greater than 0*"
{
r client kill id 0
}
assert_error
"ERR Unknown client type*"
{
r client kill type wrong_type
}
...
...
@@ -215,6 +215,7 @@ start_server {tags {"introspection"}} {
dbfilename
logfile
dir
socket-mark-id
}
if
{
!$::tls
}
{
...
...
@@ -285,16 +286,22 @@ start_server {tags {"introspection"}} {
}
}
{}
{
external:skip
}
test
{
CONFIG REWRITE handles save properly
}
{
test
{
CONFIG REWRITE handles save
and shutdown
properly
}
{
r config set save
"3600 1 300 100 60 10000"
r config set shutdown-on-sigterm
"nosave now"
r config set shutdown-on-sigint
"save"
r config rewrite
restart_server 0 true false
assert_equal
[
r config get save
]
{
save
{
3600 1 300 100 60 10000
}}
assert_equal
[
r config get shutdown-on-sigterm
]
{
shutdown-on-sigterm
{
nosave now
}}
assert_equal
[
r config get shutdown-on-sigint
]
{
shutdown-on-sigint save
}
r config set save
""
r config set shutdown-on-sigterm
"default"
r config rewrite
restart_server 0 true false
assert_equal
[
r config get save
]
{
save
{}}
assert_equal
[
r config get shutdown-on-sigterm
]
{
shutdown-on-sigterm default
}
start_server
{
config
"minimal.conf"
}
{
assert_equal
[
r config get save
]
{
save
{
3600 1 300 100 60 10000
}}
...
...
@@ -409,11 +416,11 @@ start_server {tags {"introspection"}} {
}
test
{
CONFIG SET duplicate configs
}
{
assert_error
"ERR*duplicate*"
{
r config set maxmemory 10000001 maxmemory 10000002
}
assert_error
"ERR
*duplicate*"
{
r config set maxmemory 10000001 maxmemory 10000002
}
}
test
{
CONFIG SET set immutable
}
{
assert_error
"ERR*immutable*"
{
r config set daemonize yes
}
assert_error
"ERR
*immutable*"
{
r config set daemonize yes
}
}
test
{
CONFIG GET hidden configs
}
{
...
...
@@ -448,8 +455,8 @@ start_server {tags {"introspection"}} {
start_server
{
tags
{
"introspection external:skip"
}
overrides
{
enable-protected-configs
{
no
}
enable-debug-command
{
no
}}}
{
test
{
cannot modify protected configuration - no
}
{
assert_error
"ERR*protected*"
{
r config set dir somedir
}
assert_error
"ERR*DEBUG command not allowed*"
{
r DEBUG HELP
}
assert_error
"ERR
*protected*"
{
r config set dir somedir
}
assert_error
"ERR
*DEBUG command not allowed*"
{
r DEBUG HELP
}
}
{}
{
needs:debug
}
}
...
...
@@ -464,8 +471,8 @@ start_server {config "minimal.conf" tags {"introspection external:skip"} overrid
if
{
$myaddr
!=
""
&& !
[
string match
{
127.*
}
$myaddr
]}
{
# Non-loopback client should fail
set r2
[
get_nonloopback_client
]
assert_error
"ERR*protected*"
{
$r2
config set dir somedir
}
assert_error
"ERR*DEBUG command not allowed*"
{
$r2
DEBUG HELP
}
assert_error
"ERR
*protected*"
{
$r2
config set dir somedir
}
assert_error
"ERR
*DEBUG command not allowed*"
{
$r2
DEBUG HELP
}
}
}
{}
{
needs:debug
}
}
...
...
tests/unit/moduleapi/aclcheck.tcl
View file @
d375595d
...
...
@@ -16,6 +16,7 @@ start_server {tags {"modules acl"}} {
assert
{[
dict get $entry username
]
eq
{
default
}}
assert
{[
dict get $entry context
]
eq
{
module
}}
assert
{[
dict get $entry object
]
eq
{
set
}}
assert
{[
dict get $entry reason
]
eq
{
command
}}
}
test
{
test module check acl for key perm
}
{
...
...
@@ -75,6 +76,7 @@ start_server {tags {"modules acl"}} {
assert
{[
dict get $entry username
]
eq
{
default
}}
assert
{[
dict get $entry context
]
eq
{
module
}}
assert
{[
dict get $entry object
]
eq
{
z
}}
assert
{[
dict get $entry reason
]
eq
{
key
}}
# rm call check for command permission
r acl setuser default -set
...
...
@@ -88,6 +90,7 @@ start_server {tags {"modules acl"}} {
assert
{[
dict get $entry username
]
eq
{
default
}}
assert
{[
dict get $entry context
]
eq
{
module
}}
assert
{[
dict get $entry object
]
eq
{
set
}}
assert
{[
dict get $entry reason
]
eq
{
command
}}
}
test
"Unload the module - aclcheck"
{
...
...
tests/unit/moduleapi/basics.tcl
View file @
d375595d
...
...
@@ -36,6 +36,6 @@ start_server {tags {"modules"}} {
start_server
{
tags
{
"modules external:skip"
}
overrides
{
enable-module-command no
}}
{
test
{
module command disabled
}
{
assert_error
"ERR*MODULE command not allowed*"
{
r module load $testmodule
}
assert_error
"ERR
*MODULE command not allowed*"
{
r module load $testmodule
}
}
}
\ No newline at end of file
Prev
1
2
3
4
5
6
7
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