Skip to content

Commit

Permalink
pmem: add pmem_log_set_function function + UT
Browse files Browse the repository at this point in the history
  • Loading branch information
osalyk committed Mar 20, 2024
1 parent 8004f8b commit 4478d42
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 1 deletion.
46 changes: 45 additions & 1 deletion src/include/libpmem.h
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -91,6 +91,50 @@ 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,
};

/*
* the type used for defining logging functions
*/
typedef void pmem_log_function(
/* the log level of the message */
enum pmem_log_level level,
/* name of the source file where the message coming from */
const char *file_name,
/* the source file line where the message coming from */
const int line_no,
/* the function name where the message coming from */
const char *function_name,
/* message */
const char *message);

#define PMEM_LOG_USE_DEFAULT_FUNCTION (NULL)

/*
* pmem_log_set_function - set the logging function
*/
int pmem_log_set_function(pmem_log_function *log_function);

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

/*
* pmem_log_set_function -- set the log function pointer either to
* a user-provided function pointer or to the default logging function.
*/
int
pmem_log_set_function(pmem_log_function *log_function)
{
int ret = core_log_set_function((core_log_function *)log_function);
return core_log_error_translate(ret);
}
1 change: 1 addition & 0 deletions src/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ PMEM_TESTS = \
pmem_include\
pmem_is_pmem\
pmem_is_pmem_posix\
pmem_log_set_function\
pmem_map_file\
pmem_has_auto_flush\
pmem_deep_persist\
Expand Down
1 change: 1 addition & 0 deletions src/test/pmem_log_set_function/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pmem_log_set_function
15 changes: 15 additions & 0 deletions src/test/pmem_log_set_function/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_function
OBJS = pmem_log_set_function.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_function.c)
27 changes: 27 additions & 0 deletions src/test/pmem_log_set_function/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_set_function', self.test_case)


class TEST0(PMEM_LOG):
test_case = 'test_log_set_function'


class TEST1(PMEM_LOG):
test_case = 'test_log_set_function_EAGAIN'
91 changes: 91 additions & 0 deletions src/test/pmem_log_set_function/pmem_log_set_function.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// SPDX-License-Identifier: BSD-3-Clause
/* Copyright 2024, Intel Corporation */

/*
* pmem_log_set_function.c -- unit test for pmem_log_set_function
*/

#include "unittest.h"
#include "log_internal.h"
#include "libpmem.h"

#define NO_ARGS_CONSUMED 0

#define VALIDATED_CALL 127
#define CALLED (VALIDATED_CALL + 1)

#define PMEM_LOG_CUSTOM_FUNCTION_MOCK ((pmem_log_function *) 0xA1C5D68F)

/* Mock */
static struct {
int ret;
} Core_log_set_function;

FUNC_MOCK(core_log_set_function, int, core_log_function *log_function)
FUNC_MOCK_RUN(VALIDATED_CALL) {
UT_ASSERTeq((void *)log_function,
(void *)PMEM_LOG_CUSTOM_FUNCTION_MOCK);
return Core_log_set_function.ret;
}
FUNC_MOCK_RUN_DEFAULT {
return _FUNC_REAL(core_log_set_function)(log_function);
}
FUNC_MOCK_END

/* Helper */
static int
test_log_set_function_helper(int error)
{
errno = 0;
Core_log_set_function.ret = error == NO_ERRNO ? 0 : error;
FUNC_MOCK_RCOUNTER_SET(core_log_set_function, VALIDATED_CALL);
int ret = pmem_log_set_function(PMEM_LOG_CUSTOM_FUNCTION_MOCK);
if (error == NO_ERRNO) {
UT_ASSERTeq(ret, 0);
} else {
UT_ASSERTeq(ret, 1);
UT_ASSERTeq(errno, error);
}
UT_ASSERTeq(RCOUNTER(core_log_set_function), CALLED);

return NO_ARGS_CONSUMED;
}

/* Tests */
/*
* Check:
* - if core_log_set_function is called with proper argument
* - if pmem_log_set_function return 0 (no error)
* - no errno is set
*/
static int
test_log_set_function(const struct test_case *tc, int argc, char *argv[])
{
return test_log_set_function_helper(NO_ERRNO);
}

/*
* core_log_set_function() with EAGAIN error
* Check:
* - if core_log_set_function is called with proper argument
* - if pmem_log_set_function return 1 (error via errno)
* - errno is set to EAGAIN
*/
static int
test_log_set_function_EAGAIN(const struct test_case *tc, int argc, char *argv[])
{
return test_log_set_function_helper(EAGAIN);
}

static struct test_case test_cases[] = {
TEST_CASE(test_log_set_function),
TEST_CASE(test_log_set_function_EAGAIN),
};

int
main(int argc, char *argv[])
{
START(argc, argv, "pmem_log_set_function");
TEST_CASE_PROCESS(argc, argv, test_cases, ARRAY_SIZE(test_cases));
DONE(NULL);
}

0 comments on commit 4478d42

Please sign in to comment.