diff options
author | chenyang8094 <chenyang8094@users.noreply.github.com> | 2021-09-09 16:03:05 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-09 11:03:05 +0300 |
commit | bc0c22fabca058f4b23c9a634a37f6753dd963bd (patch) | |
tree | 23c204f53ba7336a32d19117a0cd46c7abe69203 /tests/modules/basics.c | |
parent | 7c80a65484b31f397426189620bc32e68e8fd842 (diff) | |
download | redis-bc0c22fabca058f4b23c9a634a37f6753dd963bd.tar.gz |
Fix callReplyParseCollection memleak when use AutoMemory (#9446)
When parsing an array type reply, ctx will be lost when recursively parsing its
elements, which will cause a memory leak in automemory mode.
This is a result of the changes in #9202
Add test for callReplyParseCollection fix
Diffstat (limited to 'tests/modules/basics.c')
-rw-r--r-- | tests/modules/basics.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/tests/modules/basics.c b/tests/modules/basics.c index aa11fb967..a743b9edf 100644 --- a/tests/modules/basics.c +++ b/tests/modules/basics.c @@ -33,6 +33,7 @@ #define REDISMODULE_EXPERIMENTAL_API #include "redismodule.h" #include <string.h> +#include <stdlib.h> /* --------------------------------- Helpers -------------------------------- */ @@ -457,6 +458,38 @@ int TestUnlink(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { return RedisModule_ReplyWithSimpleString(ctx, "OK"); } +int TestNestedCallReplyArrayElement(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + RedisModule_AutoMemory(ctx); + REDISMODULE_NOT_USED(argv); + REDISMODULE_NOT_USED(argc); + + RedisModuleString *expect_key = RedisModule_CreateString(ctx, "mykey", strlen("mykey")); + RedisModule_SelectDb(ctx, 1); + RedisModule_Call(ctx, "LPUSH", "sc", expect_key, "myvalue"); + + RedisModuleCallReply *scan_reply = RedisModule_Call(ctx, "SCAN", "l", 0); + RedisModule_Assert(scan_reply != NULL && RedisModule_CallReplyType(scan_reply) == REDISMODULE_REPLY_ARRAY); + RedisModule_Assert(RedisModule_CallReplyLength(scan_reply) == 2); + + long long scan_cursor; + RedisModuleCallReply *cursor_reply = RedisModule_CallReplyArrayElement(scan_reply, 0); + RedisModule_Assert(RedisModule_CallReplyType(cursor_reply) == REDISMODULE_REPLY_STRING); + RedisModule_Assert(RedisModule_StringToLongLong(RedisModule_CreateStringFromCallReply(cursor_reply), &scan_cursor) == REDISMODULE_OK); + RedisModule_Assert(scan_cursor == 0); + + RedisModuleCallReply *keys_reply = RedisModule_CallReplyArrayElement(scan_reply, 1); + RedisModule_Assert(RedisModule_CallReplyType(keys_reply) == REDISMODULE_REPLY_ARRAY); + RedisModule_Assert( RedisModule_CallReplyLength(keys_reply) == 1); + + RedisModuleCallReply *key_reply = RedisModule_CallReplyArrayElement(keys_reply, 0); + RedisModule_Assert(RedisModule_CallReplyType(key_reply) == REDISMODULE_REPLY_STRING); + RedisModuleString *key = RedisModule_CreateStringFromCallReply(key_reply); + RedisModule_Assert(RedisModule_StringCompare(key, expect_key) == 0); + + RedisModule_ReplyWithSimpleString(ctx, "OK"); + return REDISMODULE_OK; +} + /* TEST.STRING.TRUNCATE -- Test truncating an existing string object. */ int TestStringTruncate(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { RedisModule_AutoMemory(ctx); @@ -795,6 +828,9 @@ int TestBasics(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { T("test.unlink",""); if (!TestAssertStringReply(ctx,reply,"OK",2)) goto fail; + T("test.nestedcallreplyarray",""); + if (!TestAssertStringReply(ctx,reply,"OK",2)) goto fail; + T("test.string.append.am",""); if (!TestAssertStringReply(ctx,reply,"foobar",6)) goto fail; @@ -894,6 +930,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) TestUnlink,"write deny-oom",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; + if (RedisModule_CreateCommand(ctx,"test.nestedcallreplyarray", + TestNestedCallReplyArrayElement,"write deny-oom",1,1,1) == REDISMODULE_ERR) + return REDISMODULE_ERR; + if (RedisModule_CreateCommand(ctx,"test.basics", TestBasics,"readonly",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; |