summaryrefslogtreecommitdiff
path: root/examples/redis-unstable/tests/modules/configaccess.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/redis-unstable/tests/modules/configaccess.c')
-rw-r--r--examples/redis-unstable/tests/modules/configaccess.c353
1 files changed, 353 insertions, 0 deletions
diff --git a/examples/redis-unstable/tests/modules/configaccess.c b/examples/redis-unstable/tests/modules/configaccess.c
new file mode 100644
index 0000000..7bc8a48
--- /dev/null
+++ b/examples/redis-unstable/tests/modules/configaccess.c
@@ -0,0 +1,353 @@
+#include "redismodule.h"
+#include <assert.h>
+#include <string.h>
+
+/* See moduleconfigs.c for registering module configs. We need to register some
+ * module configs with our module in order to test the interaction between
+ * module configs and the RM_Get/Set*Config APIs. */
+int configaccess_bool;
+
+int getBoolConfigCommand(const char *name, void *privdata) {
+ REDISMODULE_NOT_USED(name);
+ return (*(int *)privdata);
+}
+
+int setBoolConfigCommand(const char *name, int new, void *privdata, RedisModuleString **err) {
+ REDISMODULE_NOT_USED(name);
+ REDISMODULE_NOT_USED(err);
+ *(int *)privdata = new;
+ return REDISMODULE_OK;
+}
+
+/* Test command for RM_GetConfigType */
+int TestGetConfigType_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc != 2) {
+ return RedisModule_WrongArity(ctx);
+ }
+
+ size_t len;
+ const char *config_name = RedisModule_StringPtrLen(argv[1], &len);
+
+ RedisModuleConfigType type;
+ int res = RedisModule_ConfigGetType(config_name, &type);
+ if (res == REDISMODULE_ERR) {
+ RedisModule_ReplyWithError(ctx, "ERR Config does not exist");
+ return REDISMODULE_ERR;
+ }
+
+ const char *type_str;
+ switch (type) {
+ case REDISMODULE_CONFIG_TYPE_BOOL:
+ type_str = "bool";
+ break;
+ case REDISMODULE_CONFIG_TYPE_NUMERIC:
+ type_str = "numeric";
+ break;
+ case REDISMODULE_CONFIG_TYPE_STRING:
+ type_str = "string";
+ break;
+ case REDISMODULE_CONFIG_TYPE_ENUM:
+ type_str = "enum";
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ RedisModule_ReplyWithSimpleString(ctx, type_str);
+ return REDISMODULE_OK;
+}
+
+/* Test command for config iteration */
+int TestConfigIteration_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ REDISMODULE_NOT_USED(argv);
+
+ if (argc > 2) {
+ return RedisModule_WrongArity(ctx);
+ }
+
+ const char *pattern = NULL;
+ if (argc == 2) {
+ pattern = RedisModule_StringPtrLen(argv[1], NULL);
+ }
+
+ RedisModuleConfigIterator *iter = RedisModule_ConfigIteratorCreate(ctx, pattern);
+ if (!iter) {
+ RedisModule_ReplyWithError(ctx, "ERR Failed to get config iterator");
+ return REDISMODULE_ERR;
+ }
+
+ /* Start array reply for the configs */
+ RedisModule_ReplyWithArray(ctx, REDISMODULE_POSTPONED_ARRAY_LEN);
+
+ /* Iterate through the dictionary */
+ const char *config_name = NULL;
+ long count = 0;
+ while ((config_name = RedisModule_ConfigIteratorNext(iter)) != NULL) {
+ RedisModuleString *value = NULL;
+ RedisModule_ConfigGet(ctx, config_name, &value);
+
+ RedisModule_ReplyWithArray(ctx, 2);
+ RedisModule_ReplyWithStringBuffer(ctx, config_name, strlen(config_name));
+ RedisModule_ReplyWithString(ctx, value);
+
+ RedisModule_FreeString(ctx, value);
+ ++count;
+ }
+ RedisModule_ReplySetArrayLength(ctx, count);
+
+ /* Free the iterator */
+ RedisModule_ConfigIteratorRelease(ctx, iter);
+
+ return REDISMODULE_OK;
+}
+
+/* Test command for RM_GetBoolConfig */
+int TestGetBoolConfig_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc != 2) {
+ return RedisModule_WrongArity(ctx);
+ }
+
+ size_t len;
+ const char *config_name = RedisModule_StringPtrLen(argv[1], &len);
+
+ int value;
+ if (RedisModule_ConfigGetBool(ctx, config_name, &value) == REDISMODULE_ERR) {
+ RedisModule_ReplyWithError(ctx, "ERR Failed to get bool config");
+ return REDISMODULE_ERR;
+ }
+
+ RedisModule_ReplyWithLongLong(ctx, value);
+ return REDISMODULE_OK;
+}
+
+/* Test command for RM_GetNumericConfig */
+int TestGetNumericConfig_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc != 2) {
+ return RedisModule_WrongArity(ctx);
+ }
+
+ size_t len;
+ const char *config_name = RedisModule_StringPtrLen(argv[1], &len);
+
+ long long value;
+ if (RedisModule_ConfigGetNumeric(ctx, config_name, &value) == REDISMODULE_ERR) {
+ RedisModule_ReplyWithError(ctx, "ERR Failed to get numeric config");
+ return REDISMODULE_ERR;
+ }
+
+ RedisModule_ReplyWithLongLong(ctx, value);
+ return REDISMODULE_OK;
+}
+
+/* Test command for RM_GetConfig */
+int TestGetConfig_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc != 2) {
+ return RedisModule_WrongArity(ctx);
+ }
+
+ size_t len;
+ const char *config_name = RedisModule_StringPtrLen(argv[1], &len);
+
+ RedisModuleString *value;
+ if (RedisModule_ConfigGet(ctx, config_name, &value) == REDISMODULE_ERR) {
+ RedisModule_ReplyWithError(ctx, "ERR Failed to get string config");
+ return REDISMODULE_ERR;
+ }
+
+ RedisModule_ReplyWithString(ctx, value);
+ RedisModule_FreeString(ctx,value);
+ return REDISMODULE_OK;
+}
+
+/* Test command for RM_GetEnumConfig */
+int TestGetEnumConfig_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc != 2) {
+ return RedisModule_WrongArity(ctx);
+ }
+
+ size_t len;
+ const char *config_name = RedisModule_StringPtrLen(argv[1], &len);
+
+ RedisModuleString *value;
+ if (RedisModule_ConfigGetEnum(ctx, config_name, &value) == REDISMODULE_ERR) {
+ RedisModule_ReplyWithError(ctx, "ERR Failed to get enum name config");
+ return REDISMODULE_ERR;
+ }
+
+ RedisModule_ReplyWithString(ctx, value);
+ RedisModule_Free(value);
+ return REDISMODULE_OK;
+}
+
+/* Test command for RM_SetBoolConfig */
+int TestSetBoolConfig_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc != 3) {
+ return RedisModule_WrongArity(ctx);
+ }
+
+ size_t name_len, value_len;
+ const char *config_name = RedisModule_StringPtrLen(argv[1], &name_len);
+ const char *config_value = RedisModule_StringPtrLen(argv[2], &value_len);
+
+ int bool_value;
+ if (!strcasecmp(config_value, "yes")) {
+ bool_value = 1;
+ } else if (!strcasecmp(config_value, "no")) {
+ bool_value = 0;
+ } else {
+ bool_value = -1;
+ }
+
+ RedisModuleString *error = NULL;
+ int result = RedisModule_ConfigSetBool(ctx, config_name, bool_value, &error);
+ if (result == REDISMODULE_ERR) {
+ RedisModule_ReplyWithErrorFormat(ctx, "ERR Failed to set bool config %s: %s", config_name, RedisModule_StringPtrLen(error, NULL));
+ RedisModule_FreeString(ctx, error);
+ return REDISMODULE_ERR;
+ }
+
+ RedisModule_ReplyWithSimpleString(ctx, "OK");
+ return REDISMODULE_OK;
+}
+
+/* Test command for RM_SetNumericConfig */
+int TestSetNumericConfig_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc != 3) {
+ return RedisModule_WrongArity(ctx);
+ }
+
+ size_t name_len;
+ const char *config_name = RedisModule_StringPtrLen(argv[1], &name_len);
+
+ long long value;
+ const char *value_str= RedisModule_StringPtrLen(argv[2], NULL);
+ if (value_str[0] == '-') {
+ if (RedisModule_StringToLongLong(argv[2], &value) != REDISMODULE_OK) {
+ RedisModule_ReplyWithError(ctx, "ERR Invalid numeric value");
+ return REDISMODULE_ERR;
+ }
+ } else {
+ if (RedisModule_StringToULongLong(argv[2], (unsigned long long*)&value) != REDISMODULE_OK) {
+ RedisModule_ReplyWithError(ctx, "ERR Invalid numeric value");
+ return REDISMODULE_ERR;
+ }
+ }
+
+ RedisModuleString *error = NULL;
+ int result = RedisModule_ConfigSetNumeric(ctx, config_name, value, &error);
+ if (result == REDISMODULE_OK) {
+ RedisModule_ReplyWithSimpleString(ctx, "OK");
+ } else {
+ RedisModule_ReplyWithErrorFormat(ctx, "ERR Failed to set numeric config %s: %s", config_name, RedisModule_StringPtrLen(error, NULL));
+ RedisModule_FreeString(ctx, error);
+ return REDISMODULE_ERR;
+ }
+
+ return REDISMODULE_OK;
+}
+
+/* Test command for RM_SetConfig */
+int TestSetConfig_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc != 3) {
+ return RedisModule_WrongArity(ctx);
+ }
+
+ size_t name_len;
+ const char *config_name = RedisModule_StringPtrLen(argv[1], &name_len);
+
+ RedisModuleString *error = NULL;
+ int result = RedisModule_ConfigSet(ctx, config_name, argv[2], &error);
+ if (result == REDISMODULE_OK) {
+ RedisModule_ReplyWithSimpleString(ctx, "OK");
+ } else {
+ RedisModule_ReplyWithErrorFormat(ctx, "ERR Failed to set string config %s: %s", config_name, RedisModule_StringPtrLen(error, NULL));
+ RedisModule_FreeString(ctx, error);
+ return REDISMODULE_ERR;
+ }
+
+ return REDISMODULE_OK;
+}
+
+/* Test command for RM_SetEnumConfig with name */
+int TestSetEnumConfig_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (argc < 3) {
+ return RedisModule_WrongArity(ctx);
+ }
+
+ const char *config_name = RedisModule_StringPtrLen(argv[1], NULL);
+
+ RedisModuleString *error = NULL;
+ int result = RedisModule_ConfigSetEnum(ctx, config_name, argv[2], &error);
+
+ if (result == REDISMODULE_OK) {
+ RedisModule_ReplyWithSimpleString(ctx, "OK");
+ } else {
+ RedisModule_ReplyWithErrorFormat(ctx, "ERR Failed to set enum config %s: %s", config_name, RedisModule_StringPtrLen(error, NULL));
+ RedisModule_FreeString(ctx, error);
+ return REDISMODULE_ERR;
+ }
+
+ return REDISMODULE_OK;
+}
+
+int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ REDISMODULE_NOT_USED(argv);
+ REDISMODULE_NOT_USED(argc);
+
+ if (RedisModule_Init(ctx, "configaccess", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx, "configaccess.getconfigs",
+ TestConfigIteration_RedisCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx, "configaccess.getbool",
+ TestGetBoolConfig_RedisCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx, "configaccess.getnumeric",
+ TestGetNumericConfig_RedisCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx, "configaccess.get",
+ TestGetConfig_RedisCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx, "configaccess.getenum",
+ TestGetEnumConfig_RedisCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx, "configaccess.setbool",
+ TestSetBoolConfig_RedisCommand, "write", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx, "configaccess.setnumeric",
+ TestSetNumericConfig_RedisCommand, "write", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx, "configaccess.set",
+ TestSetConfig_RedisCommand, "write", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx, "configaccess.setenum",
+ TestSetEnumConfig_RedisCommand, "write", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx, "configaccess.getconfigtype", TestGetConfigType_RedisCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ if (RedisModule_RegisterBoolConfig(ctx, "bool", 1, REDISMODULE_CONFIG_DEFAULT,
+ getBoolConfigCommand, setBoolConfigCommand, NULL, &configaccess_bool) == REDISMODULE_ERR) {
+ RedisModule_Log(ctx, "warning", "Failed to register configaccess_bool");
+ return REDISMODULE_ERR;
+ }
+
+ RedisModule_Log(ctx, "debug", "Loading configaccess module configuration");
+ if (RedisModule_LoadConfigs(ctx) == REDISMODULE_ERR) {
+ RedisModule_Log(ctx, "warning", "Failed to load configaccess module configuration");
+ return REDISMODULE_ERR;
+ }
+
+ return REDISMODULE_OK;
+}