Skip to content

Commit

Permalink
pmem: add pmem_log_[get/set]_treshold functions + UT
Browse files Browse the repository at this point in the history
  • Loading branch information
osalyk committed Mar 19, 2024
1 parent 8004f8b commit d364813
Show file tree
Hide file tree
Showing 12 changed files with 406 additions and 6 deletions.
47 changes: 47 additions & 0 deletions src/include/libpmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,53 @@ 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 library to stop working immediately */
PMEM_LOG_LEVEL_FATAL,
/* an error that causes the library to stop working properly */
PMEM_LOG_LEVEL_ERROR,
/* an errors that could be handled in the upper level */
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 above this level
* 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 level
*/
int pmem_log_set_threshold(enum pmem_log_threshold threshold,
enum pmem_log_level level);

/*
* pmem_log_get_threshold - get the logging threshold level
*/
int pmem_log_get_threshold(enum pmem_log_threshold threshold,
enum pmem_log_level *level);

#ifdef __cplusplus
}
#endif
Expand Down
24 changes: 24 additions & 0 deletions src/libpmem/libpmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,27 @@ pmem_errormsg(void)
{
return pmem_errormsgU();
}

/*
* pmem_log_set_threshold -- set the log level threshold
*/
int
pmem_log_set_threshold(enum pmem_log_threshold threshold,
enum pmem_log_level level)
{
int ret = core_log_set_threshold((enum core_log_threshold)threshold,
(enum core_log_level)level);
return core_log_error_translate(ret);
}

/*
* pmem_log_get_threshold -- get the log level threshold
*/
int
pmem_log_get_threshold(enum pmem_log_threshold threshold,
enum pmem_log_level *level)
{
int ret = core_log_get_threshold((enum core_log_threshold)threshold,
(enum core_log_level *)level);
return core_log_error_translate(ret);
}
7 changes: 1 addition & 6 deletions src/libpmem/pmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,6 @@
* Func_memset_nodrain is used by memset_nodrain() to call one of:
* memset_nodrain_libc()
* memset_nodrain_movnt()
*
* DEBUG LOGGING
*
* Many of the functions here get called hundreds of times from loops
* iterating over ranges, making the usual LOG() calls at level 3
* impractical. The call tracing log for those functions is set at 15.
*/

#include <sys/mman.h>
Expand All @@ -152,6 +146,7 @@
#include "valgrind_internal.h"
#include "os_deep.h"
#include "auto_flush.h"
#include "log_internal.h"

struct pmem_funcs {
struct memmove_nodrain memmove_funcs;
Expand Down
2 changes: 2 additions & 0 deletions src/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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\
Expand Down
1 change: 1 addition & 0 deletions src/test/pmem_log_get_treshold/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pmem_log_get_treshold
20 changes: 20 additions & 0 deletions src/test/pmem_log_get_treshold/Makefile
Original file line number Diff line number Diff line change
@@ -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)
27 changes: 27 additions & 0 deletions src/test/pmem_log_get_treshold/TESTS.py
Original file line number Diff line number Diff line change
@@ -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'
116 changes: 116 additions & 0 deletions src/test/pmem_log_get_treshold/pmem_log_get_treshold.c
Original file line number Diff line number Diff line change
@@ -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[] = {
CORE_LOG_THRESHOLD,
CORE_LOG_THRESHOLD_AUX
};

static enum core_log_level core_levels[] = {
CORE_LOG_LEVEL_HARK,
CORE_LOG_LEVEL_FATAL,
CORE_LOG_LEVEL_ERROR,
CORE_LOG_LEVEL_WARNING,
CORE_LOG_LEVEL_NOTICE,
CORE_LOG_LEVEL_INFO,
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, "_log_get_treshold");
TEST_CASE_PROCESS(argc, argv, test_cases, ARRAY_SIZE(test_cases));
DONE(NULL);
}
1 change: 1 addition & 0 deletions src/test/pmem_log_set_treshold/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pmem_log_set_treshold
15 changes: 15 additions & 0 deletions src/test/pmem_log_set_treshold/Makefile
Original file line number Diff line number Diff line change
@@ -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)
31 changes: 31 additions & 0 deletions src/test/pmem_log_set_treshold/TESTS.py
Original file line number Diff line number Diff line change
@@ -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'
Loading

0 comments on commit d364813

Please sign in to comment.