diff --git a/src/include/libpmem.h b/src/include/libpmem.h index a1201889644..ad1a11c6e7f 100644 --- a/src/include/libpmem.h +++ b/src/include/libpmem.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * libpmem.h -- definitions of libpmem entry points @@ -91,6 +91,57 @@ const char *pmem_check_version(unsigned major_required, const char *pmem_errormsg(void); +/* + * Available log levels. Log levels are used in the logging API calls + * to indicate logging message severity. Log levels are also used + * to define thresholds for the logging. + */ +enum pmem_log_level { + /* only basic library info */ + PMEM_LOG_LEVEL_HARK, + /* an error that causes the program to stop working immediately */ + PMEM_LOG_LEVEL_FATAL, + /* an error that causes the current operation to fail */ + PMEM_LOG_LEVEL_ERROR, + /* + * an unexpected situation that does NOT cause + * the current operation to fail + */ + PMEM_LOG_LEVEL_WARNING, + /* non-massive info mainly related to public API function completions */ + PMEM_LOG_LEVEL_NOTICE, + /* massive info e.g. every write operation indication */ + PMEM_LOG_LEVEL_INFO, + /* debug info e.g. write operation dump */ + PMEM_LOG_LEVEL_DEBUG, +}; + +enum pmem_log_threshold { + /* + * the main threshold level - the logging messages less severe than + * indicated by this threshold's value won't trigger the logging + * functions + */ + PMEM_LOG_THRESHOLD, + /* + * the auxiliary threshold level - may or may not be used by the logging + * function + */ + PMEM_LOG_THRESHOLD_AUX, +}; + +/* + * pmem_log_set_threshold - set the logging threshold value + */ +int pmem_log_set_threshold(enum pmem_log_threshold threshold, + enum pmem_log_level value); + +/* + * pmem_log_get_threshold - get the logging threshold value + */ +int pmem_log_get_threshold(enum pmem_log_threshold threshold, + enum pmem_log_level *value); + #ifdef __cplusplus } #endif diff --git a/src/libpmem/libpmem.c b/src/libpmem/libpmem.c index d2705f67cfb..514ee05d022 100644 --- a/src/libpmem/libpmem.c +++ b/src/libpmem/libpmem.c @@ -96,3 +96,27 @@ pmem_errormsg(void) { return pmem_errormsgU(); } + +/* + * pmem_log_set_threshold -- set the logging threshold value + */ +int +pmem_log_set_threshold(enum pmem_log_threshold threshold, + enum pmem_log_level value) +{ + int ret = core_log_set_threshold((enum core_log_threshold)threshold, + (enum core_log_level)value); + return core_log_error_translate(ret); +} + +/* + * pmem_log_get_threshold -- get the logging level threshold value + */ +int +pmem_log_get_threshold(enum pmem_log_threshold threshold, + enum pmem_log_level *value) +{ + int ret = core_log_get_threshold((enum core_log_threshold)threshold, + (enum core_log_level *)value); + return core_log_error_translate(ret); +} diff --git a/src/test/Makefile b/src/test/Makefile index 961172eac35..a3558c3f6eb 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -161,6 +161,8 @@ PMEM_TESTS = \ pmem_include\ pmem_is_pmem\ pmem_is_pmem_posix\ + pmem_log_get_treshold\ + pmem_log_set_treshold\ pmem_map_file\ pmem_has_auto_flush\ pmem_deep_persist\ diff --git a/src/test/pmem_log_get_treshold/.gitignore b/src/test/pmem_log_get_treshold/.gitignore new file mode 100644 index 00000000000..39976e5d27f --- /dev/null +++ b/src/test/pmem_log_get_treshold/.gitignore @@ -0,0 +1 @@ +pmem_log_get_treshold diff --git a/src/test/pmem_log_get_treshold/Makefile b/src/test/pmem_log_get_treshold/Makefile new file mode 100644 index 00000000000..5db71427838 --- /dev/null +++ b/src/test/pmem_log_get_treshold/Makefile @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + +# +# src/test/pmem_log_get_treshold/Makefile -- build pmem_log_get_treshold unit test +# + +TARGET = pmem_log_get_treshold +OBJS = pmem_log_get_treshold.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +# required for proper mock integration +LIBPMEMCOMMON=internal-debug +LIBPMEM=internal-debug + +include ../Makefile.inc +LDFLAGS += $(call extract_funcs, pmem_log_get_treshold.c) diff --git a/src/test/pmem_log_get_treshold/TESTS.py b/src/test/pmem_log_get_treshold/TESTS.py new file mode 100755 index 00000000000..c01d1556353 --- /dev/null +++ b/src/test/pmem_log_get_treshold/TESTS.py @@ -0,0 +1,27 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +# The 'debug' build is chosen arbitrarily to ensure these tests are run only +# once. No dynamic libraries are used nor .static_* builds are available. +@t.require_build('debug') +class PMEM_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('pmem_log_get_treshold', self.test_case) + + +class TEST0(PMEM_LOG): + test_case = 'test_log_get_treshold' + + +class TEST1(PMEM_LOG): + test_case = 'test_log_get_treshold_EAGAIN' diff --git a/src/test/pmem_log_get_treshold/pmem_log_get_treshold.c b/src/test/pmem_log_get_treshold/pmem_log_get_treshold.c new file mode 100644 index 00000000000..1f96a71359f --- /dev/null +++ b/src/test/pmem_log_get_treshold/pmem_log_get_treshold.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * pmem_log_get_treshold.c -- unit test for pmem_log_get_treshold + */ + +#include "unittest.h" +#include "log_internal.h" +#include "libpmem.h" + +#define NO_ARGS_CONSUMED 0 + +#define VALIDATED_CALL 127 +#define CALLED (VALIDATED_CALL + 1) + +static enum core_log_threshold core_tresholds[] = { + [PMEM_LOG_THRESHOLD] = CORE_LOG_THRESHOLD, + [PMEM_LOG_THRESHOLD_AUX] = CORE_LOG_THRESHOLD_AUX +}; + +static enum core_log_level core_levels[] = { + [PMEM_LOG_LEVEL_HARK] = CORE_LOG_LEVEL_HARK, + [PMEM_LOG_LEVEL_FATAL] = CORE_LOG_LEVEL_FATAL, + [PMEM_LOG_LEVEL_ERROR] = CORE_LOG_LEVEL_ERROR, + [PMEM_LOG_LEVEL_WARNING] = CORE_LOG_LEVEL_WARNING, + [PMEM_LOG_LEVEL_NOTICE] = CORE_LOG_LEVEL_NOTICE, + [PMEM_LOG_LEVEL_INFO] = CORE_LOG_LEVEL_INFO, + [PMEM_LOG_LEVEL_DEBUG] = CORE_LOG_LEVEL_DEBUG +}; + +/* Mock */ +static struct { + enum core_log_threshold exp_threshold; + enum core_log_level level; + int ret; +} Core_log_get_treshold; + +FUNC_MOCK(core_log_get_threshold, int, enum core_log_threshold threshold, + enum core_log_level *level) + FUNC_MOCK_RUN(VALIDATED_CALL) { + UT_ASSERTeq(threshold, Core_log_get_treshold.exp_threshold); + if (Core_log_get_treshold.ret == 0) + *level = Core_log_get_treshold.level; + return Core_log_get_treshold.ret; + } +FUNC_MOCK_RUN_DEFAULT { + return _FUNC_REAL(core_log_get_threshold)(threshold, level); +} +FUNC_MOCK_END + +/* Helper */ +static int +test_log_get_treshold_helper(int error) +{ + errno = 0; + Core_log_get_treshold.ret = error == NO_ERRNO ? 0 : error; + for (enum pmem_log_threshold treshold = PMEM_LOG_THRESHOLD; + treshold <= PMEM_LOG_THRESHOLD_AUX; treshold++) { + Core_log_get_treshold.exp_threshold = core_tresholds[treshold]; + for (enum pmem_log_level exp_level = PMEM_LOG_LEVEL_HARK; + exp_level <= PMEM_LOG_LEVEL_DEBUG; exp_level++) { + enum pmem_log_level level; + Core_log_get_treshold.level = core_levels[exp_level]; + FUNC_MOCK_RCOUNTER_SET(core_log_get_threshold, + VALIDATED_CALL); + int ret = pmem_log_get_threshold(treshold, &level); + if (error == NO_ERRNO) { + UT_ASSERTeq(ret, 0); + UT_ASSERTeq(level, exp_level); + } else { + UT_ASSERTeq(ret, 1); + UT_ASSERTeq(errno, error); + } + UT_ASSERTeq(RCOUNTER(core_log_get_threshold), CALLED); + /* no need to test the error path for all values */ + if (error != NO_ERRNO) + return NO_ARGS_CONSUMED; + } + } + return NO_ARGS_CONSUMED; +} + +/* Tests */ +/* + * Check: + * - if core_log_get_treshold is called with proper arguments + * - if pmem_log_get_treshold return 0 (no error) + * - if each PMEM_LOG_LEVEL corespond to relevant CORE_LOG_LEVEL + * - no errno is set + */ +static int +test_log_get_treshold(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_get_treshold_helper(NO_ERRNO); +} + +/* Check pmem_log_get_threshold EAGAIN error handling. */ +static int +test_log_get_treshold_EAGAIN(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_get_treshold_helper(EAGAIN); +} + +static struct test_case test_cases[] = { + TEST_CASE(test_log_get_treshold), + TEST_CASE(test_log_get_treshold_EAGAIN), +}; + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "pmem_log_get_treshold"); + TEST_CASE_PROCESS(argc, argv, test_cases, ARRAY_SIZE(test_cases)); + DONE(NULL); +} diff --git a/src/test/pmem_log_set_treshold/.gitignore b/src/test/pmem_log_set_treshold/.gitignore new file mode 100644 index 00000000000..c56248dfa65 --- /dev/null +++ b/src/test/pmem_log_set_treshold/.gitignore @@ -0,0 +1 @@ +pmem_log_set_treshold diff --git a/src/test/pmem_log_set_treshold/Makefile b/src/test/pmem_log_set_treshold/Makefile new file mode 100644 index 00000000000..5e13b3cc238 --- /dev/null +++ b/src/test/pmem_log_set_treshold/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +TARGET = pmem_log_set_treshold +OBJS = pmem_log_set_treshold.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +# required for proper mock integration +LIBPMEMCOMMON=internal-debug +LIBPMEM=internal-debug + +include ../Makefile.inc +LDFLAGS += $(call extract_funcs, pmem_log_set_treshold.c) diff --git a/src/test/pmem_log_set_treshold/TESTS.py b/src/test/pmem_log_set_treshold/TESTS.py new file mode 100755 index 00000000000..781acaa44a2 --- /dev/null +++ b/src/test/pmem_log_set_treshold/TESTS.py @@ -0,0 +1,31 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +# The 'debug' build is chosen arbitrarily to ensure these tests are run only +# once. No dynamic libraries are used nor .static_* builds are available. +@t.require_build('debug') +class PMEM_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('pmem_log_set_treshold', self.test_case) + + +class TEST0(PMEM_LOG): + test_case = 'test_log_set_treshold' + + +class TEST1(PMEM_LOG): + test_case = 'test_log_set_treshold_EAGAIN' + + +class TEST2(PMEM_LOG): + test_case = 'test_log_set_treshold_EINVAL' diff --git a/src/test/pmem_log_set_treshold/pmem_log_set_treshold.c b/src/test/pmem_log_set_treshold/pmem_log_set_treshold.c new file mode 100644 index 00000000000..887ac02289a --- /dev/null +++ b/src/test/pmem_log_set_treshold/pmem_log_set_treshold.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * pmem_log_set_treshold.c -- unit test for pmem_log_set_treshold + */ + +#include "unittest.h" +#include "log_internal.h" +#include "libpmem.h" + +#define NO_ARGS_CONSUMED 0 + +#define VALIDATED_CALL 127 +#define CALLED (VALIDATED_CALL + 1) + +static enum core_log_threshold core_tresholds[] = { + [PMEM_LOG_THRESHOLD] = CORE_LOG_THRESHOLD, + [PMEM_LOG_THRESHOLD_AUX] = CORE_LOG_THRESHOLD_AUX +}; + +static enum core_log_level core_levels[] = { + [PMEM_LOG_LEVEL_HARK] = CORE_LOG_LEVEL_HARK, + [PMEM_LOG_LEVEL_FATAL] = CORE_LOG_LEVEL_FATAL, + [PMEM_LOG_LEVEL_ERROR] = CORE_LOG_LEVEL_ERROR, + [PMEM_LOG_LEVEL_WARNING] = CORE_LOG_LEVEL_WARNING, + [PMEM_LOG_LEVEL_NOTICE] = CORE_LOG_LEVEL_NOTICE, + [PMEM_LOG_LEVEL_INFO] = CORE_LOG_LEVEL_INFO, + [PMEM_LOG_LEVEL_DEBUG] = CORE_LOG_LEVEL_DEBUG +}; + +/* Mock */ +static struct { + enum core_log_threshold exp_threshold; + enum core_log_level exp_level; + int ret; +} Core_log_set_treshold; + +FUNC_MOCK(core_log_set_threshold, int, enum core_log_threshold threshold, + enum core_log_level level) + FUNC_MOCK_RUN(VALIDATED_CALL) { + UT_ASSERTeq(threshold, Core_log_set_treshold.exp_threshold); + UT_ASSERTeq(level, Core_log_set_treshold.exp_level); + return Core_log_set_treshold.ret; + } +FUNC_MOCK_RUN_DEFAULT { + return _FUNC_REAL(core_log_set_threshold)(threshold, level); +} +FUNC_MOCK_END + +/* Helper */ +static int +test_log_set_treshold_helper(int error) +{ + errno = 0; + Core_log_set_treshold.ret = error == NO_ERRNO ? 0 : error; + for (enum pmem_log_threshold treshold = PMEM_LOG_THRESHOLD; + treshold <= PMEM_LOG_THRESHOLD_AUX; treshold++) { + Core_log_set_treshold.exp_threshold = core_tresholds[treshold]; + for (enum pmem_log_level level = PMEM_LOG_LEVEL_HARK; + level <= PMEM_LOG_LEVEL_DEBUG; level++) { + Core_log_set_treshold.exp_level = core_levels[level]; + FUNC_MOCK_RCOUNTER_SET(core_log_set_threshold, + VALIDATED_CALL); + int ret = pmem_log_set_threshold(treshold, level); + if (error == NO_ERRNO) { + UT_ASSERTeq(ret, 0); + } else { + UT_ASSERTeq(ret, 1); + UT_ASSERTeq(errno, error); + } + UT_ASSERTeq(RCOUNTER(core_log_set_threshold), CALLED); + /* no need to test the error path for all values */ + if (error != NO_ERRNO) + return NO_ARGS_CONSUMED; + } + } + return NO_ARGS_CONSUMED; +} + +/* Tests */ +/* + * Check: + * - if core_log_set_treshold is called with proper arguments + * - if pmempmem_log_set_treshold return 0 (no error) + * - if each PMEM_LOG_LEVEL corespond to relevant CORE_LOG_LEVEL + * - no errno is set + */ +static int +test_log_set_treshold(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_treshold_helper(NO_ERRNO); +} + +/* Check pmem_log_set_threshold EAGAIN error handling. */ +static int +test_log_set_treshold_EAGAIN(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_treshold_helper(EAGAIN); +} + +/* Check pmem_log_set_threshold EINVAL error handling. */ +static int +test_log_set_treshold_EINVAL(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_treshold_helper(EINVAL); +} + +static struct test_case test_cases[] = { + TEST_CASE(test_log_set_treshold), + TEST_CASE(test_log_set_treshold_EAGAIN), + TEST_CASE(test_log_set_treshold_EINVAL), +}; + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "pmem_log_set_treshold"); + TEST_CASE_PROCESS(argc, argv, test_cases, ARRAY_SIZE(test_cases)); + DONE(NULL); +}