diff --git a/src/ctl/ctl.c b/src/ctl/ctl.c index b1e9de9d8..d9cfb18eb 100644 --- a/src/ctl/ctl.c +++ b/src/ctl/ctl.c @@ -27,9 +27,9 @@ #include "base_alloc/base_alloc_global.h" #include "ctl_internal.h" +#include "uthash/utlist.h" #include "utils/utils_common.h" #include "utils_log.h" -#include "utlist.h" #ifdef _WIN32 #define strtok_r strtok_s @@ -49,13 +49,25 @@ static int ctl_global_first_free = 0; static umf_ctl_node_t CTL_NODE(global)[CTL_MAX_ENTRIES]; +static void *(*ctl_malloc_fn)(size_t) = NULL; +static void (*ctl_free_fn)(void *) = NULL; + +void ctl_init(void *(*Malloc)(size_t), void (*Free)(void *)) { + if (Malloc) { + ctl_malloc_fn = Malloc; + } + if (Free) { + ctl_free_fn = Free; + } +} + typedef struct optional_umf_result_t { bool is_valid; umf_result_t value; } optional_umf_result_t; void *Zalloc(size_t sz) { - void *ptr = umf_ba_global_alloc(sz); + void *ptr = ctl_malloc_fn(sz); if (ptr) { memset(ptr, 0, sz); } @@ -64,7 +76,7 @@ void *Zalloc(size_t sz) { char *Strdup(const char *s) { size_t len = strlen(s) + 1; - char *p = umf_ba_global_alloc(len); + char *p = ctl_malloc_fn(len); if (p) { memcpy(p, s, len); } @@ -121,9 +133,9 @@ static void ctl_delete_indexes(umf_ctl_index_utlist_t *indexes) { LL_DELETE(indexes, elem); if (elem) { if (elem->arg) { - umf_ba_global_free(elem->arg); + ctl_free_fn(elem->arg); } - umf_ba_global_free(elem); + ctl_free_fn(elem); } } } @@ -139,7 +151,7 @@ static void ctl_query_cleanup_real_args(const umf_ctl_node_t *n, void *real_arg, switch (source) { case CTL_QUERY_CONFIG_INPUT: - umf_ba_global_free(real_arg); + ctl_free_fn(real_arg); break; case CTL_QUERY_PROGRAMMATIC: break; @@ -153,7 +165,7 @@ static void ctl_query_cleanup_real_args(const umf_ctl_node_t *n, void *real_arg, * structure */ static void *ctl_parse_args(const struct ctl_argument *arg_proto, char *arg) { - char *dest_arg = umf_ba_global_alloc(arg_proto->dest_size); + char *dest_arg = ctl_malloc_fn(arg_proto->dest_size); if (dest_arg == NULL) { return NULL; } @@ -176,7 +188,7 @@ static void *ctl_parse_args(const struct ctl_argument *arg_proto, char *arg) { return dest_arg; error_parsing: - umf_ba_global_free(dest_arg); + ctl_free_fn(dest_arg); return NULL; } @@ -372,7 +384,7 @@ ctl_find_and_execute_node(const umf_ctl_node_t *nodes, void *ctx, goto error; } // argument is a wildcard so we need to allocate it from va_list - node_arg = umf_ba_global_alloc(n->arg->dest_size); + node_arg = ctl_malloc_fn(n->arg->dest_size); if (node_arg == NULL) { goto error; } @@ -386,9 +398,9 @@ ctl_find_and_execute_node(const umf_ctl_node_t *nodes, void *ctx, } umf_ctl_index_utlist_t *entry = NULL; - entry = umf_ba_global_alloc(sizeof(*entry)); + entry = ctl_malloc_fn(sizeof(*entry)); if (entry == NULL) { - umf_ba_global_free(arg); + ctl_free_fn(arg); goto error; } @@ -462,13 +474,13 @@ ctl_find_and_execute_node(const umf_ctl_node_t *nodes, void *ctx, } } out: - umf_ba_global_free(parse_str); + ctl_free_fn(parse_str); ctl_delete_indexes(indexes); return ret; error: ctl_delete_indexes(indexes); - umf_ba_global_free(parse_str); + ctl_free_fn(parse_str); ret.is_valid = false; return ret; } @@ -599,7 +611,7 @@ umf_result_t ctl_load_config_from_string(struct ctl *ctl, void *ctx, umf_result_t ret = ctl_load_config(ctl, ctx, buf); - umf_ba_global_free(buf); + ctl_free_fn(buf); return ret; } @@ -661,7 +673,7 @@ umf_result_t ctl_load_config_from_file(struct ctl *ctl, void *ctx, ret = ctl_load_config(ctl, ctx, buf); - umf_ba_global_free(buf); + ctl_free_fn(buf); error_file_parse: (void)fclose(fp); diff --git a/src/ctl/ctl_internal.h b/src/ctl/ctl_internal.h index a45fa7732..bd4f5b9b4 100644 --- a/src/ctl/ctl_internal.h +++ b/src/ctl/ctl_internal.h @@ -122,6 +122,7 @@ struct ctl { }; void initialize_global_ctl(void); +void ctl_init(void *(*Malloc)(size_t), void (*Free)(void *)); umf_result_t ctl_load_config_from_string(struct ctl *ctl, void *ctx, const char *cfg_string); diff --git a/src/libumf.c b/src/libumf.c index fb01eae57..d393d44b3 100644 --- a/src/libumf.c +++ b/src/libumf.c @@ -12,6 +12,7 @@ #include #include "base_alloc_global.h" +#include "ctl/ctl_internal.h" #include "ipc_cache.h" #include "memory_pool_internal.h" #include "memory_provider_internal.h" @@ -36,7 +37,7 @@ static UTIL_ONCE_FLAG initMutexOnce = UTIL_ONCE_FLAG_INIT; static void initialize_init_mutex(void) { utils_mutex_init(&initMutex); } static umf_ctl_node_t CTL_NODE(umf)[] = {CTL_CHILD(provider), CTL_CHILD(pool), - CTL_NODE_END}; + CTL_CHILD(logger), CTL_NODE_END}; void initialize_global_ctl(void) { CTL_REGISTER_MODULE(NULL, umf); } @@ -65,6 +66,7 @@ umf_result_t umfInit(void) { } LOG_DEBUG("UMF IPC cache initialized"); + ctl_init(umf_ba_global_alloc, umf_ba_global_free); initialize_global_ctl(); } diff --git a/src/memory_pool.c b/src/memory_pool.c index 004f42d9e..4b0173c73 100644 --- a/src/memory_pool.c +++ b/src/memory_pool.c @@ -36,7 +36,7 @@ char CTL_DEFAULT_VALUES[UMF_DEFAULT_SIZE][UMF_DEFAULT_LEN] = {0}; static struct ctl umf_pool_ctl_root; -static void ctl_init(void); +static void pool_ctl_init(void); static umf_result_t CTL_SUBTREE_HANDLER(CTL_NONAME, by_handle)( void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, @@ -66,7 +66,7 @@ static umf_result_t CTL_SUBTREE_HANDLER(default)( umf_ctl_index_utlist_t *indexes, const char *extra_name, umf_ctl_query_type_t queryType, va_list args) { (void)indexes, (void)source, (void)ctx, (void)args; - utils_init_once(&mem_pool_ctl_initialized, ctl_init); + utils_init_once(&mem_pool_ctl_initialized, pool_ctl_init); if (strstr(extra_name, "{}") != NULL) { // We might implement it in future - it requires store copy of va_list @@ -148,7 +148,7 @@ static const struct ctl_argument CTL_ARG(by_handle) = CTL_ARG_PTR; umf_ctl_node_t CTL_NODE(pool)[] = {CTL_CHILD_WITH_ARG(by_handle), CTL_LEAF_SUBTREE(default), CTL_NODE_END}; -static void ctl_init(void) { +static void pool_ctl_init(void) { utils_mutex_init(&ctl_mtx); CTL_REGISTER_MODULE(&umf_pool_ctl_root, stats); } @@ -223,7 +223,7 @@ static umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops, pool->provider = provider; } - utils_init_once(&mem_pool_ctl_initialized, ctl_init); + utils_init_once(&mem_pool_ctl_initialized, pool_ctl_init); pool->flags = flags; pool->ops = *ops; diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 7125d2603..e26017e79 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -5,7 +5,8 @@ include(${UMF_CMAKE_SOURCE_DIR}/cmake/helpers.cmake) include(FindThreads) -set(UMF_UTILS_SOURCES_COMMON utils_common.c utils_log.c utils_load_library.c) +set(UMF_UTILS_SOURCES_COMMON utils_common.c utils_log.c utils_load_library.c + ../ctl/ctl.c) set(UMF_UTILS_SOURCES_POSIX utils_posix_common.c utils_posix_concurrency.c) set(UMF_UTILS_SOURCES_LINUX utils_linux_common.c) set(UMF_UTILS_SOURCES_MACOSX utils_macosx_common.c) diff --git a/src/utils/utils_log.c b/src/utils/utils_log.c index 960ae4686..6d162e3c8 100644 --- a/src/utils/utils_log.c +++ b/src/utils/utils_log.c @@ -28,6 +28,7 @@ #include +#include "ctl/ctl_internal.h" #include "utils_assert.h" #include "utils_common.h" #include "utils_log.h" @@ -61,14 +62,16 @@ char const __umf_str_1__all_cmake_vars[] = #define MAX_ENV_LEN 2048 typedef struct { - int timestamp; - int pid; + bool enableTimestamp; + bool enamblePid; utils_log_level_t level; utils_log_level_t flushLevel; FILE *output; + const char *file_name; } utils_log_config_t; -utils_log_config_t loggerConfig = {0, 0, LOG_ERROR, LOG_ERROR, NULL}; +utils_log_config_t loggerConfig = {false, false, LOG_ERROR, + LOG_ERROR, NULL, NULL}; static const char *level_to_str(utils_log_level_t l) { switch (l) { @@ -185,7 +188,7 @@ static void utils_log_internal(utils_log_level_t level, int perror, int h_size = sizeof(header); memset(header, 0, sizeof(header)); - if (loggerConfig.timestamp) { + if (loggerConfig.enableTimestamp) { time_t now = time(NULL); struct tm tm_info; #ifdef _WIN32 @@ -200,7 +203,7 @@ static void utils_log_internal(utils_log_level_t level, int perror, h_size -= tmp; } - if (loggerConfig.pid) { + if (loggerConfig.enamblePid) { ASSERT(h_size > 0); tmp = snprintf(h_pos, h_size, "PID:%-6lu TID:%-6lu ", (unsigned long)pid, (unsigned long)tid); @@ -254,8 +257,10 @@ void utils_log_init(void) { const char *arg; if (utils_parse_var(envVar, "output:stdout", NULL)) { loggerConfig.output = stdout; + loggerConfig.file_name = "stdout"; } else if (utils_parse_var(envVar, "output:stderr", NULL)) { loggerConfig.output = stderr; + loggerConfig.file_name = "stderr"; } else if (utils_parse_var(envVar, "output:file", &arg)) { loggerConfig.output = NULL; const char *argEnd = strstr(arg, ";"); @@ -284,6 +289,7 @@ void utils_log_init(void) { loggerConfig.output = NULL; return; } + loggerConfig.file_name = file; } else { loggerConfig.output = stderr; LOG_ERR("Logging output not set - logging disabled (UMF_LOG = \"%s\")", @@ -293,15 +299,15 @@ void utils_log_init(void) { } if (utils_parse_var(envVar, "timestamp:yes", NULL)) { - loggerConfig.timestamp = 1; + loggerConfig.enableTimestamp = 1; } else if (utils_parse_var(envVar, "timestamp:no", NULL)) { - loggerConfig.timestamp = 0; + loggerConfig.enableTimestamp = 0; } if (utils_parse_var(envVar, "pid:yes", NULL)) { - loggerConfig.pid = 1; + loggerConfig.enamblePid = 1; } else if (utils_parse_var(envVar, "pid:no", NULL)) { - loggerConfig.pid = 0; + loggerConfig.enamblePid = 0; } if (utils_parse_var(envVar, "level:debug", NULL)) { @@ -328,9 +334,257 @@ void utils_log_init(void) { loggerConfig.flushLevel = LOG_FATAL; } - LOG_INFO( - "Logger enabled (" LOG_STR_UMF_VERSION - "level: %s, flush: %s, pid: %s, timestamp: %s)", - level_to_str(loggerConfig.level), level_to_str(loggerConfig.flushLevel), - bool_to_str(loggerConfig.pid), bool_to_str(loggerConfig.timestamp)); + LOG_INFO("Logger enabled (" LOG_STR_UMF_VERSION + "level: %s, flush: %s, pid: %s, timestamp: %s)", + level_to_str(loggerConfig.level), + level_to_str(loggerConfig.flushLevel), + bool_to_str(loggerConfig.enamblePid), + bool_to_str(loggerConfig.enableTimestamp)); } + +// this is needed for logger unit test +#ifndef DISABLE_CTL_LOGGER +static umf_result_t +CTL_READ_HANDLER(timestamp)(void *ctx, umf_ctl_query_source_t source, void *arg, + size_t size, umf_ctl_index_utlist_t *indexes) { + /* suppress unused-parameter errors */ + (void)source, (void)indexes, (void)ctx; + + bool *arg_out = (bool *)arg; + + if (arg_out == NULL || size < sizeof(bool)) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + *arg_out = loggerConfig.enableTimestamp; + return UMF_RESULT_SUCCESS; +} + +static umf_result_t +CTL_WRITE_HANDLER(timestamp)(void *ctx, umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { + /* suppress unused-parameter errors */ + (void)source, (void)indexes, (void)ctx; + + bool arg_in = *(bool *)arg; + + if (size < sizeof(bool)) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + loggerConfig.enableTimestamp = arg_in; + LOG_INFO("Logger print timestamp set to %s", + bool_to_str(loggerConfig.enableTimestamp)); + return UMF_RESULT_SUCCESS; +} + +static umf_result_t CTL_READ_HANDLER(pid)(void *ctx, + umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { + /* suppress unused-parameter errors */ + (void)source, (void)indexes, (void)ctx; + + bool *arg_out = (bool *)arg; + + if (arg_out == NULL || size < sizeof(bool)) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + *arg_out = loggerConfig.enamblePid; + return UMF_RESULT_SUCCESS; +} + +static umf_result_t CTL_WRITE_HANDLER(pid)(void *ctx, + umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { + /* suppress unused-parameter errors */ + (void)source, (void)indexes, (void)ctx; + + bool arg_in = *(bool *)arg; + + if (size < sizeof(bool)) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + loggerConfig.enamblePid = arg_in; + LOG_INFO("Logger print pid %s set to", + bool_to_str(loggerConfig.enamblePid)); + return UMF_RESULT_SUCCESS; +} + +static umf_result_t CTL_READ_HANDLER(level)(void *ctx, + umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { + /* suppress unused-parameter errors */ + (void)source, (void)indexes, (void)ctx; + + bool *arg_out = (bool *)arg; + + if (arg_out == NULL || size < sizeof(utils_log_level_t)) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + *arg_out = loggerConfig.level; + return UMF_RESULT_SUCCESS; +} + +static umf_result_t CTL_WRITE_HANDLER(level)(void *ctx, + umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { + /* suppress unused-parameter errors */ + (void)source, (void)indexes, (void)ctx; + + utils_log_level_t *arg_in = (utils_log_level_t *)arg; + + if (arg_in == NULL || *arg_in < LOG_DEBUG || *arg_in > LOG_FATAL || + size < sizeof(int)) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + utils_log_level_t old = loggerConfig.level; + + // if new log level is higher then LOG_INFO print log before changing log level + // so if user changes from LOG_INFO to higher log level, it will get information about change anyway + if (*arg_in > LOG_INFO) { + LOG_INFO("Logger level changed from %s to %s", level_to_str(old), + level_to_str(*arg_in)); + loggerConfig.level = *arg_in; + } else { + loggerConfig.level = *arg_in; + LOG_INFO("Logger level changed from %s to %s", level_to_str(old), + level_to_str(loggerConfig.level)); + } + + return UMF_RESULT_SUCCESS; +} + +static umf_result_t +CTL_READ_HANDLER(flush_level)(void *ctx, umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { + /* suppress unused-parameter errors */ + (void)source, (void)indexes, (void)ctx; + + utils_log_level_t *arg_out = (utils_log_level_t *)arg; + + if (arg_out == NULL || size < sizeof(utils_log_level_t)) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + *arg_out = loggerConfig.flushLevel; + return UMF_RESULT_SUCCESS; +} + +static umf_result_t +CTL_WRITE_HANDLER(flush_level)(void *ctx, umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { + /* suppress unused-parameter errors */ + (void)source, (void)indexes, (void)ctx; + + utils_log_level_t *arg_in = (utils_log_level_t *)arg; + + if (arg_in == NULL || *arg_in < LOG_DEBUG || *arg_in > LOG_FATAL || + size < sizeof(int)) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + loggerConfig.flushLevel = *arg_in; + LOG_INFO("Logger flush level set to %s", + level_to_str(loggerConfig.flushLevel)); + return UMF_RESULT_SUCCESS; +} + +static umf_result_t CTL_READ_HANDLER(output)(void *ctx, + umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { + /* suppress unused-parameter errors */ + (void)source, (void)indexes, (void)ctx; + + const char **arg_out = (const char **)arg; + if (arg_out == NULL || size < sizeof(const char *)) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + if (loggerConfig.output == NULL) { + *arg_out = "disabled"; + return UMF_RESULT_SUCCESS; + } + + *arg_out = loggerConfig.file_name; + return UMF_RESULT_SUCCESS; +} + +static umf_result_t CTL_WRITE_HANDLER(output)(void *ctx, + umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { + /* suppress unused-parameter errors */ + (void)source, (void)indexes, (void)ctx; + + const char *arg_in = *(const char **)arg; + if (size < sizeof(const char *)) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + FILE *oldHandle = loggerConfig.output; + const char *oldName = + loggerConfig.file_name ? loggerConfig.file_name : "disabled"; + + if (arg_in == NULL) { + if (loggerConfig.output) { + LOG_INFO("Logger disabled"); + if (oldHandle != stdout && oldHandle != stderr) { + fclose(oldHandle); + } + loggerConfig.output = NULL; + loggerConfig.file_name = NULL; + } + return UMF_RESULT_SUCCESS; + } + + FILE *newHandle = NULL; + + if (strcmp(arg_in, "stdout") == 0) { + newHandle = stdout; + loggerConfig.file_name = "stdout"; + } else if (strcmp(arg_in, "stderr") == 0) { + newHandle = stderr; + loggerConfig.file_name = "stderr"; + } else { + newHandle = fopen(arg_in, "a"); + if (!newHandle) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + loggerConfig.file_name = arg_in; + } + + loggerConfig.output = newHandle; + LOG_INFO("Logger output changed from %s to %s", oldName, + loggerConfig.file_name); + + if (oldHandle && oldHandle != stdout && oldHandle != stderr) { + fclose(oldHandle); + } + + return UMF_RESULT_SUCCESS; +} + +static const struct ctl_argument CTL_ARG(timestamp) = CTL_ARG_BOOLEAN; +static const struct ctl_argument CTL_ARG(pid) = CTL_ARG_BOOLEAN; +static const struct ctl_argument CTL_ARG(level) = CTL_ARG_INT; +static const struct ctl_argument CTL_ARG(flush_level) = CTL_ARG_INT; +static const struct ctl_argument + CTL_ARG(output) = CTL_ARG_STRING(MAX_FILE_PATH); + +const umf_ctl_node_t CTL_NODE(logger)[] = { + CTL_LEAF_RW(timestamp), CTL_LEAF_RW(pid), CTL_LEAF_RW(level), + CTL_LEAF_RW(flush_level), CTL_LEAF_RW(output), CTL_NODE_END, +}; +#endif diff --git a/src/utils/utils_log.h b/src/utils/utils_log.h index ab40121ce..c0e0a9572 100644 --- a/src/utils/utils_log.h +++ b/src/utils/utils_log.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2024 Intel Corporation + * Copyright (C) 2024-2025 Intel Corporation * * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -14,6 +14,8 @@ extern "C" { #endif +#include "ctl/ctl_internal.h" + typedef enum { LOG_DEBUG, LOG_INFO, @@ -47,6 +49,8 @@ void utils_plog(utils_log_level_t level, const char *func, const char *format, ...) __attribute__((format(printf, 3, 4))); #endif +extern const umf_ctl_node_t CTL_NODE(logger)[]; + #ifdef __cplusplus } #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d4e027e47..3f21def05 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -195,10 +195,12 @@ add_umf_test( SRCS memoryProviderAPI.cpp LIBS ${UMF_UTILS_FOR_TEST} ${UMF_BA_FOR_TEST}) -add_umf_test( - NAME logger - SRCS utils/utils_log.cpp ${UMF_UTILS_SOURCES} - LIBS ${UMF_LOGGER_LIBS}) +if(NOT UMF_BUILD_SHARED_LIBRARY) + add_umf_test( + NAME logger + SRCS utils/utils_log.cpp ${UMF_UTILS_SOURCES} ../src/ctl/ctl.c + LIBS ${UMF_LOGGER_LIBS} ${UMF_BA_FOR_TEST}) +endif() add_umf_test( NAME ctl_unittest diff --git a/test/ctl/ctl_api.cpp b/test/ctl/ctl_api.cpp index 55120961b..35f8b9e44 100644 --- a/test/ctl/ctl_api.cpp +++ b/test/ctl/ctl_api.cpp @@ -378,3 +378,57 @@ TEST_F(CtlTest, ctlDefaultMultithreadedProvider) { } } #endif + +TEST_F(test, ctl_logger_basic_rw) { + bool ts_set = true; + ASSERT_EQ(umfCtlSet("umf.logger.timestamp", &ts_set, sizeof(ts_set)), + UMF_RESULT_SUCCESS); + bool ts_get = false; + ASSERT_EQ(umfCtlGet("umf.logger.timestamp", &ts_get, sizeof(ts_get)), + UMF_RESULT_SUCCESS); + EXPECT_TRUE(ts_get); + + bool pid_set = 1; + ASSERT_EQ(umfCtlSet("umf.logger.pid", &pid_set, sizeof(pid_set)), + UMF_RESULT_SUCCESS); + bool pid_get = 0; + ASSERT_EQ(umfCtlGet("umf.logger.pid", &pid_get, sizeof(pid_get)), + UMF_RESULT_SUCCESS); + EXPECT_EQ(pid_get, 1); + + int level_set = 1; + ASSERT_EQ(umfCtlSet("umf.logger.level", &level_set, sizeof(level_set)), + UMF_RESULT_SUCCESS); + int level_get = 0; + ASSERT_EQ(umfCtlGet("umf.logger.level", &level_get, sizeof(level_get)), + UMF_RESULT_SUCCESS); + EXPECT_EQ(level_get, 1); + + int flush_set = 2; + ASSERT_EQ( + umfCtlSet("umf.logger.flush_level", &flush_set, sizeof(flush_set)), + UMF_RESULT_SUCCESS); + int flush_get = 0; + ASSERT_EQ( + umfCtlGet("umf.logger.flush_level", &flush_get, sizeof(flush_get)), + UMF_RESULT_SUCCESS); + EXPECT_EQ(flush_get, 2); + + const char *out_name = "stdout"; + ASSERT_EQ(umfCtlSet("umf.logger.output", &out_name, sizeof(out_name)), + UMF_RESULT_SUCCESS); + const char *out_get = NULL; + ASSERT_EQ(umfCtlGet("umf.logger.output", &out_get, sizeof(out_get)), + UMF_RESULT_SUCCESS); + EXPECT_STREQ(out_get, "stdout"); +} + +TEST_F(test, ctl_logger_output_file) { + const char *file_name = "ctl_log.txt"; + ASSERT_EQ(umfCtlSet("umf.logger.output", &file_name, sizeof(file_name)), + UMF_RESULT_SUCCESS); + const char *out_get = NULL; + ASSERT_EQ(umfCtlGet("umf.logger.output", &out_get, sizeof(out_get)), + UMF_RESULT_SUCCESS); + EXPECT_STREQ(out_get, file_name); +} diff --git a/test/ctl/ctl_debug.c b/test/ctl/ctl_debug.c index e8730d896..ddff10eea 100644 --- a/test/ctl/ctl_debug.c +++ b/test/ctl/ctl_debug.c @@ -11,6 +11,7 @@ * ctl_debug.c -- implementation of the debug CTL namespace */ +#include #include #include "ctl/ctl_internal.h" @@ -183,4 +184,7 @@ static const umf_ctl_node_t CTL_NODE(debug)[] = { */ void debug_ctl_register(struct ctl *ctl) { CTL_REGISTER_MODULE(ctl, debug); } -void initialize_debug_ctl(void) { debug_ctl_register(&ctl_debug); } +void initialize_debug_ctl(void) { + debug_ctl_register(&ctl_debug); + ctl_init(malloc, free); +} diff --git a/test/utils/utils_log.cpp b/test/utils/utils_log.cpp index cce61db58..171a031f3 100644 --- a/test/utils/utils_log.cpp +++ b/test/utils/utils_log.cpp @@ -1,8 +1,11 @@ -// Copyright (C) 2024 Intel Corporation +// Copyright (C) 2024-2025 Intel Corporation // Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include + #include "base.hpp" +#include "ctl/ctl_internal.h" #include "test_helpers.h" #define MOCK_FILE_PTR (FILE *)0xBADBEEF @@ -93,7 +96,7 @@ int mock_strerror_windows(char *buff, size_t s, int errnum) { } extern "C" { - +#define DISABLE_CTL_LOGGER 1 const char *env_variable = ""; #define fopen(A, B) mock_fopen(A, B) #define fputs(A, B) mock_fputs(A, B) @@ -135,13 +138,13 @@ void helper_checkConfig(utils_log_config_t *expected, utils_log_config_t *is) { EXPECT_EQ(expected->level, is->level); EXPECT_EQ(expected->flushLevel, is->flushLevel); EXPECT_EQ(expected->output, is->output); - EXPECT_EQ(expected->timestamp, is->timestamp); - EXPECT_EQ(expected->pid, is->pid); + EXPECT_EQ(expected->enableTimestamp, is->enableTimestamp); + EXPECT_EQ(expected->enamblePid, is->enamblePid); } TEST_F(test, parseEnv_errors) { expected_message = ""; - loggerConfig = {0, 0, LOG_ERROR, LOG_ERROR, NULL}; + loggerConfig = {false, false, LOG_ERROR, LOG_ERROR, NULL, ""}; expect_fput_count = 0; expected_stream = stderr; @@ -195,14 +198,16 @@ TEST_F(test, parseEnv) { {"output:file," + std::string(256, 'x'), MOCK_FILE_PTR}, {"output:file," + std::string(257, 'x'), NULL}, }; - std::vector> timestamps = { - {"timestamp:yes", 1}, - {"timestamp:invalid", 0}, - {"timestamp:no", 0}, - {"", 0}}; - - std::vector> pids = { - {"pid:yes", 1}, {"pid:invalid", 0}, {"pid:no", 0}, {"", 0}}; + std::vector> timestamps = { + {"timestamp:yes", true}, + {"timestamp:invalid", false}, + {"timestamp:no", false}, + {"", false}}; + + std::vector> pids = {{"pid:yes", true}, + {"pid:invalid", false}, + {"pid:no", false}, + {"", false}}; for (const auto &logLevel : logLevels) { for (const auto &flushLevel : flushLevels) { for (const auto &output : outputs) { @@ -212,7 +217,8 @@ TEST_F(test, parseEnv) { flushLevel.first + ";" + output.first + ";" + timestamp.first + ";" + pid.first; - b = loggerConfig = {0, 0, LOG_ERROR, LOG_ERROR, NULL}; + b = loggerConfig = {false, false, LOG_ERROR, + LOG_ERROR, NULL, ""}; expect_fput_count = 0; expect_fopen_count = 0; expected_stream = stderr; @@ -229,8 +235,8 @@ TEST_F(test, parseEnv) { expect_fopen_count = 1; } expected_stream = output.second; - b.timestamp = timestamp.second; - b.pid = pid.second; + b.enableTimestamp = timestamp.second; + b.enamblePid = pid.second; b.flushLevel = (utils_log_level_t)flushLevel.second; b.level = (utils_log_level_t)logLevel.second; @@ -284,7 +290,8 @@ TEST_F(test, log_levels) { expected_stream = stderr; for (int i = LOG_DEBUG; i <= LOG_ERROR; i++) { for (int j = LOG_DEBUG; j <= LOG_ERROR; j++) { - loggerConfig = {0, 0, (utils_log_level_t)i, LOG_DEBUG, stderr}; + loggerConfig = {false, false, (utils_log_level_t)i, + LOG_DEBUG, stderr, ""}; if (i > j) { expect_fput_count = 0; expect_fflush_count = 0; @@ -307,7 +314,7 @@ TEST_F(test, log_outputs) { expect_fflush_count = 1; expected_message = "[DEBUG UMF] " + MOCK_FN_NAME + ": example log\n"; for (auto o : outs) { - loggerConfig = {0, 0, LOG_DEBUG, LOG_DEBUG, o}; + loggerConfig = {false, false, LOG_DEBUG, LOG_DEBUG, o, ""}; expected_stream = o; helper_test_log(LOG_DEBUG, MOCK_FN_NAME.c_str(), "%s", "example log"); } @@ -318,7 +325,8 @@ TEST_F(test, flush_levels) { expect_fput_count = 1; for (int i = LOG_DEBUG; i <= LOG_ERROR; i++) { for (int j = LOG_DEBUG; j <= LOG_ERROR; j++) { - loggerConfig = {0, 0, LOG_DEBUG, (utils_log_level_t)i, stderr}; + loggerConfig = {false, false, LOG_DEBUG, (utils_log_level_t)i, + stderr, ""}; if (i > j) { expect_fflush_count = 0; } else { @@ -335,7 +343,7 @@ TEST_F(test, flush_levels) { TEST_F(test, long_log) { expect_fput_count = 1; expect_fflush_count = 1; - loggerConfig = {0, 0, LOG_DEBUG, LOG_DEBUG, stderr}; + loggerConfig = {false, false, LOG_DEBUG, LOG_DEBUG, stderr, ""}; expected_message = "[DEBUG UMF] " + MOCK_FN_NAME + ": " + std::string(8189 - MOCK_FN_NAME.size(), 'x') + "\n"; helper_test_log(LOG_DEBUG, MOCK_FN_NAME.c_str(), "%s", @@ -350,7 +358,7 @@ TEST_F(test, long_log) { TEST_F(test, timestamp_log) { expect_fput_count = 1; expect_fflush_count = 1; - loggerConfig = {1, 0, LOG_DEBUG, LOG_DEBUG, stderr}; + loggerConfig = {true, false, LOG_DEBUG, LOG_DEBUG, stderr, ""}; // TODO: for now we do not check output message, // as it requires more sophisticated message validation (a.k.a regrex) expected_message = ""; @@ -360,7 +368,7 @@ TEST_F(test, timestamp_log) { TEST_F(test, pid_log) { expect_fput_count = 1; expect_fflush_count = 1; - loggerConfig = {0, 1, LOG_DEBUG, LOG_DEBUG, stderr}; + loggerConfig = {false, true, LOG_DEBUG, LOG_DEBUG, stderr, ""}; // TODO: for now we do not check output message, // as it requires more sophisticated message validation (a.k.a regrex) expected_message = ""; @@ -368,7 +376,7 @@ TEST_F(test, pid_log) { } TEST_F(test, log_fatal) { - loggerConfig = {0, 0, LOG_DEBUG, LOG_DEBUG, NULL}; + loggerConfig = {false, false, LOG_DEBUG, LOG_DEBUG, NULL, ""}; expected_stream = stderr; expect_fput_count = 1; expect_fflush_count = 1; @@ -382,7 +390,7 @@ TEST_F(test, log_macros) { expected_stream = stderr; expect_fput_count = 1; expect_fflush_count = 1; - loggerConfig = {0, 0, LOG_DEBUG, LOG_DEBUG, stderr}; + loggerConfig = {false, false, LOG_DEBUG, LOG_DEBUG, stderr, ""}; expected_message = "[DEBUG UMF] TestBody: example log\n"; fput_count = 0; @@ -429,7 +437,7 @@ template void helper_test_plog(Args... args) { } TEST_F(test, plog_basic) { - loggerConfig = {0, 0, LOG_DEBUG, LOG_DEBUG, stderr}; + loggerConfig = {false, false, LOG_DEBUG, LOG_DEBUG, stderr, ""}; expected_stream = stderr; errno = 1; strerr = "test error"; @@ -445,7 +453,7 @@ TEST_F(test, plog_basic) { } TEST_F(test, plog_invalid) { - loggerConfig = {0, 0, LOG_DEBUG, LOG_DEBUG, stderr}; + loggerConfig = {false, false, LOG_DEBUG, LOG_DEBUG, stderr, ""}; expected_stream = stderr; errno = INVALID_ERRNO; strerr = "test error"; @@ -461,7 +469,7 @@ TEST_F(test, plog_invalid) { } TEST_F(test, plog_long_message) { - loggerConfig = {0, 0, LOG_DEBUG, LOG_DEBUG, stderr}; + loggerConfig = {false, false, LOG_DEBUG, LOG_DEBUG, stderr, ""}; expected_stream = stderr; expect_fput_count = 1; expect_fflush_count = 1; @@ -482,7 +490,7 @@ TEST_F(test, plog_long_message) { } TEST_F(test, plog_long_error) { - loggerConfig = {0, 0, LOG_DEBUG, LOG_DEBUG, stderr}; + loggerConfig = {false, false, LOG_DEBUG, LOG_DEBUG, stderr, ""}; expected_stream = stderr; expect_fput_count = 1; expect_fflush_count = 1; @@ -508,7 +516,7 @@ TEST_F(test, log_pmacros) { expected_stream = stderr; expect_fput_count = 1; expect_fflush_count = 1; - loggerConfig = {0, 0, LOG_DEBUG, LOG_DEBUG, stderr}; + loggerConfig = {false, false, LOG_DEBUG, LOG_DEBUG, stderr, ""}; errno = 1; strerr = "test error";