From 81a2894f847b5972273108bea55926fc5e7d94a5 Mon Sep 17 00:00:00 2001 From: Michal Bloch Date: Thu, 20 Dec 2018 16:24:00 +0100 Subject: [PATCH] tests: reinstate 100% libdlog unit test coverage Change-Id: I4d5fb273567a63c04d21a87434cf532c5b62f383 Signed-off-by: Michal Bloch --- Makefile.am | 8 +-- include/loglimiter-internal.h | 27 +++++++++ src/libdlog/dynamic_config.c | 6 +- src/libdlog/loglimiter.c | 22 +------ src/tests/dynamic_config.c | 35 +++++++++++ src/tests/libdlog_base.c | 20 +++++++ src/tests/libdlog_pipe.c | 15 +++++ src/tests/limiter.c | 134 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 240 insertions(+), 27 deletions(-) create mode 100644 include/loglimiter-internal.h diff --git a/Makefile.am b/Makefile.am index aa39abf..8fe3534 100644 --- a/Makefile.am +++ b/Makefile.am @@ -212,15 +212,15 @@ src_tests_test_common_LDFLAGS = $(AM_LDFLAGS) src_tests_limiter_SOURCES = src/tests/limiter.c src/libdlog/loglimiter.c src/shared/logconfig.c src/shared/logcommon.c src_tests_limiter_CFLAGS = $(check_CFLAGS) -src_tests_limiter_LDFLAGS = $(AM_LDFLAGS) +src_tests_limiter_LDFLAGS = $(AM_LDFLAGS) -Wl,--wrap=snprintf,--wrap=malloc,--wrap=time src_tests_dynamic_config_SOURCES = src/tests/dynamic_config.c src/libdlog/dynamic_config.c src/shared/logcommon.c src/shared/logconfig.c src_tests_dynamic_config_CFLAGS = $(check_CFLAGS) -pthread -src_tests_dynamic_config_LDFLAGS = $(AM_LDFLAGS) -pthread -Wl,--wrap=read,--wrap=syslog_critical_failure,--wrap=inotify_init1,--wrap=inotify_add_watch,--wrap=log_config_read_file +src_tests_dynamic_config_LDFLAGS = $(AM_LDFLAGS) -pthread -Wl,--wrap=read,--wrap=syslog_critical_failure,--wrap=inotify_init1,--wrap=inotify_add_watch,--wrap=log_config_read_file,--wrap=asprintf src_tests_libdlog_pipe_SOURCES = src/tests/libdlog_pipe.c src/libdlog/log_pipe.c src/shared/logcommon.c src/shared/logconfig.c src/shared/queued_entry.c src/shared/translate_syslog.c src/shared/parsers.c src_tests_libdlog_pipe_CFLAGS = $(check_CFLAGS) -src_tests_libdlog_pipe_LDFLAGS = $(AM_LDFLAGS) -Wl,--wrap=syslog_critical_failure,--wrap=connect,--wrap=write,--wrap=recv_pipe,--wrap=dup2 +src_tests_libdlog_pipe_LDFLAGS = $(AM_LDFLAGS) -Wl,--wrap=syslog_critical_failure,--wrap=connect,--wrap=write,--wrap=recv_pipe,--wrap=dup2,--wrap=socket src_tests_libdlog_android_SOURCES = src/tests/libdlog_android.c src/libdlog/log_android.c src/shared/logconfig.c src/shared/logcommon.c src_tests_libdlog_android_CFLAGS = $(check_CFLAGS) @@ -228,7 +228,7 @@ src_tests_libdlog_android_LDFLAGS = $(AM_LDFLAGS) -Wl,--wrap=logger_open_buffer_ src_tests_libdlog_base_SOURCES = src/tests/libdlog_base.c src/libdlog/log.c src/shared/logcommon.c src/shared/logconfig.c src_tests_libdlog_base_CFLAGS = $(check_CFLAGS) -src_tests_libdlog_base_LDFLAGS = $(AM_LDFLAGS) -Wl,--wrap=log_config_read +src_tests_libdlog_base_LDFLAGS = $(AM_LDFLAGS) -Wl,--wrap=log_config_read,--wrap=snprintf src_tests_queued_entry_SOURCES = src/tests/queued_entry.c src/shared/queued_entry.c src/shared/parsers.c src/shared/translate_syslog.c src/shared/logconfig.c src/shared/logcommon.c src_tests_queued_entry_CFLAGS = $(check_CFLAGS) diff --git a/include/loglimiter-internal.h b/include/loglimiter-internal.h new file mode 100644 index 0000000..87a4570 --- /dev/null +++ b/include/loglimiter-internal.h @@ -0,0 +1,27 @@ +#pragma once + +#ifndef LOGLIMITER_INTERNAL_H_ +#define LOGLIMITER_INTERNAL_H_ + +#include + +enum rule_type { + RULE_STATIC, + RULE_DEFAULT +}; + +struct rule { + struct rule* prev; + unsigned hash; + int prio; + int limit; + int hit; + time_t start; + char tag[MAX_CONF_KEY_LEN]; + enum rule_type type; +}; + +int __log_limiter_initialize(struct rule *rules_table); +unsigned util_hash_key(const char* s, int c); + +#endif // LOGLIMITER_INTERNAL_H_ diff --git a/src/libdlog/dynamic_config.c b/src/libdlog/dynamic_config.c index f744d6b..c947ff5 100644 --- a/src/libdlog/dynamic_config.c +++ b/src/libdlog/dynamic_config.c @@ -85,9 +85,9 @@ bool __dynamic_config_create(struct log_config *config) return false; if (asprintf(&inotify_path, "%s/%s", extra_config_path, DYNAMIC_CONFIG_FILENAME) < 0) { - inotify_path = NULL;// LCOV_EXCL_LINE - syslog_critical_failure("DLog: out of memory");// LCOV_EXCL_LINE - return false; // LCOV_EXCL_LINE + inotify_path = NULL; + syslog_critical_failure("DLog: out of memory"); + return false; } if (!__setup_runtime_watch(extra_config_path)) { diff --git a/src/libdlog/loglimiter.c b/src/libdlog/loglimiter.c index 8e7beb7..351ec3a 100644 --- a/src/libdlog/loglimiter.c +++ b/src/libdlog/loglimiter.c @@ -31,6 +31,7 @@ /* Included for priorities level */ #include #include "loglimiter.h" +#include "loglimiter-internal.h" #include /* Some random big odd number to make hash more diverse */ @@ -38,25 +39,6 @@ #define TIME_FRAME 60 -enum rule_type { - RULE_STATIC, - RULE_DEFAULT -}; - -struct rule { - /* TODO: List element handle, the list could be embedded - into structure some day, like kernel lists */ - struct rule* prev; - - unsigned hash; - int prio; - int limit; - int hit; - time_t start; - char tag[MAX_CONF_KEY_LEN]; - enum rule_type type; -}; - typedef int (*hash_cmp_func_t)(struct rule*, struct rule*); typedef int (*hash_match_func_t)(struct rule*, unsigned, const char*, int); @@ -163,7 +145,7 @@ static int util_prio_to_char(int prio) /* The key is built from TAG and priority by DJB algorithm (Dan Bernstein). * Key is only 31 bits long. Negative values are keep to hold NULL bucket */ -static unsigned util_hash_key(const char* s, int c) +unsigned util_hash_key(const char* s, int c) { unsigned hash = (unsigned)c; diff --git a/src/tests/dynamic_config.c b/src/tests/dynamic_config.c index 60f879c..61f7d50 100644 --- a/src/tests/dynamic_config.c +++ b/src/tests/dynamic_config.c @@ -1,12 +1,16 @@ +// C #include #include #include +#include +// POSIX #include #include #include #include +// DLog #include pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER; @@ -52,8 +56,12 @@ int __wrap_inotify_add_watch(int fd, const char *pathname, uint32_t mask) return INOTIFY_WD; } +static bool fail_read; ssize_t __wrap_read(int fd, void *buf, size_t count) { + if (fail_read) + return -1; + struct ievent_with_filename { struct inotify_event ie; char filename[NAME_MAX + 1]; @@ -82,6 +90,19 @@ int __wrap_log_config_read_file(struct log_config *config, const char *filename) return lcrf_retval; } +static bool fail_asprintf; +int __wrap_asprintf(char **strp, const char *fmt, ...) +{ + if (fail_asprintf) + return -1; + + va_list va; + va_start(va, fmt); + const int ret = vasprintf(strp, fmt, va); + va_end(va); + return ret; +} + int main() { // check whether these blow up when called before init @@ -97,6 +118,12 @@ int main() log_config_set(&conf, DYNAMIC_CONFIG_CONF_KEY, "/"); + fail_asprintf = true; + assert(!__dynamic_config_create(&conf)); + assert(critical_failure_detected); + critical_failure_detected = false; + fail_asprintf = false; + fail_inotify_init = true; assert(!__dynamic_config_create(&conf)); assert(critical_failure_detected); @@ -131,6 +158,14 @@ int main() __dynamic_config_update(); assert(update_plog_called); assert(limiter_update_called); + update_plog_called = false; + limiter_update_called = false; + + fail_read = true; + __dynamic_config_update(); + assert(!update_plog_called); + assert(!limiter_update_called); + fail_read = false; __dynamic_config_destroy(); } diff --git a/src/tests/libdlog_base.c b/src/tests/libdlog_base.c index 7b6a501..8c6dee6 100644 --- a/src/tests/libdlog_base.c +++ b/src/tests/libdlog_base.c @@ -50,6 +50,21 @@ bool __dynamic_config_create(struct log_config *config) { return use_dynamic_con static bool dynamic_config_called; void __dynamic_config_update() { dynamic_config_called = true; } +bool fail_snprintf; +int __wrap_snprintf(char *str, size_t size, const char *format, ...) +{ + if (fail_snprintf && !strcmp(format, "enable_%s")) { + errno = -ENAMETOOLONG; + return -1; + } + + va_list va; + va_start(va, format); + const int ret = vsnprintf(str, size, format, va); + va_end(va); + return ret; +} + int main() { __dlog_fini(); @@ -113,4 +128,9 @@ int main() log_config_set(&CONFIG, "enable_system", "0"); assert(__dlog_print(LOG_ID_SYSTEM, DLOG_ERROR, "tag", "msg") == DLOG_ERROR_NONE); __dlog_fini(); + + fail_snprintf = true; + assert(__dlog_print(LOG_ID_SYSTEM, DLOG_ERROR, "tag", "msg") == 45835705); + fail_snprintf = false; + __dlog_fini(); } diff --git a/src/tests/libdlog_pipe.c b/src/tests/libdlog_pipe.c index 85e3f1b..fd3022e 100644 --- a/src/tests/libdlog_pipe.c +++ b/src/tests/libdlog_pipe.c @@ -68,6 +68,17 @@ int __wrap_recv_pipe(int sockfd, int timeout_ms) return retval; } +static bool fail_socket; +int __wrap_socket(int domain, int type, int protocol) +{ + if (fail_socket) { + errno = errno_to_set; + return -1; + } + + return 17; +} + int main() { struct log_config conf = {NULL, NULL}; @@ -142,6 +153,10 @@ int main() TC(0, 0, 1, 13, -1, "xx", 1, 1, 1); assert(expected_timeout == MIN_WAIT_PIPE_MS); + fail_socket = true; + TC(0, 0, 0, 56, -1, "xx", 0, 0, 0); + fail_socket = false; + TC(1, 0, 0, 27, -1, "xx", 1, 0, 0); #define WTC(FW,ERR,RES,CC,CW,CR) TC(0,FW,0,ERR,RES,"xx",CC,CW,CR) diff --git a/src/tests/limiter.c b/src/tests/limiter.c index 8ec2bb9..1bbd1d9 100644 --- a/src/tests/limiter.c +++ b/src/tests/limiter.c @@ -1,7 +1,14 @@ +// C #include +#include +// POSIX +#include + +// DLog #include #include +#include static size_t get_rulecount() { size_t cnt = 0; @@ -14,6 +21,41 @@ static size_t get_rulecount() { return cnt; } +static int fail_snprintf; +int __wrap_snprintf(char *str, size_t size, const char *format, ...) +{ + if (fail_snprintf && !--fail_snprintf) + return -1; + + va_list va; + va_start(va, format); + const int ret = vsnprintf(str, size, format, va); + va_end(va); + return ret; +} + +static int fail_malloc; +void *__real_malloc(size_t size); +void *__wrap_malloc(size_t size) +{ + return fail_malloc == 1 && size == sizeof(struct rule) + || fail_malloc == 2 && size != sizeof(struct rule) + ? NULL + : __real_malloc(size) + ; +} + +static bool fail_time; +static bool future_time; +time_t __real_time(time_t *t); +time_t __wrap_time(time_t *t) +{ + if (fail_time) + return -1; + + return __real_time(t) + (future_time ? 40000 : 0); +} + int main() { __log_limiter_destroy(); // check whether it explodes if called before init @@ -38,12 +80,41 @@ int main() assert(0 == __log_limiter_pass_log("BAR", 'E')); } + fail_malloc = 1; + __log_limiter_update(&conf); + for (int i = 0; i < 100; ++i) { + assert(1 == __log_limiter_pass_log("FOO", 'F')); + assert(1 == __log_limiter_pass_log("BAR", 'F')); + assert(1 == __log_limiter_pass_log("BAR", 'E')); + } + + fail_malloc = 2; + __log_limiter_update(&conf); + for (int i = 0; i < 100; ++i) { + assert(1 == __log_limiter_pass_log("FOO", 'F')); + assert(1 == __log_limiter_pass_log("BAR", 'F')); + assert(1 == __log_limiter_pass_log("BAR", 'E')); + } + + fail_malloc = 0; + __log_limiter_destroy(); + assert(__log_limiter_create(&conf)); + for (int i = 0; i < 7; ++i) assert(1 == __log_limiter_pass_log("FOO", 'E')); assert(-1 == __log_limiter_pass_log("FOO", 'E')); for (int i = 0; i < 2; ++i) assert(0 == __log_limiter_pass_log("FOO", 'E')); + fail_time = true; + assert(1 == __log_limiter_pass_log("FOO", 'E')); + fail_time = false; + assert(0 == __log_limiter_pass_log("FOO", 'E')); + future_time = true; + assert(1 == __log_limiter_pass_log("FOO", 'E')); + future_time = false; + assert(1 == __log_limiter_pass_log("FOO", 'E')); + int rulecount = get_rulecount(); assert(rulecount == 4); @@ -111,6 +182,69 @@ int main() #undef A + for (int i = 1; i <= 2; ++i) { + struct rule *r = NULL; + char buf[128]; + fail_snprintf = i; + assert(__log_limiter_dump_rule(&r, buf, sizeof buf) == -1); + } + fail_snprintf = 0; + + struct rule r1 = { + .prio = 'E', + .hash = util_hash_key("*", '*'), + .tag = "QWE", + .limit = 0, + }, r2 = { + .prev = &r1, + .prio = 'E', + .hash = util_hash_key("*", '*'), + .tag = "QWE", + .limit = 0, + }; + __log_limiter_destroy(); + __log_limiter_initialize(&r1); + + assert(1 == __log_limiter_pass_log("FOO", 'E')); + + /* Searching a hashmap kinda doesn't work if you + * fake hashes (esp. identical ones) so this just + * checks whether stuff explodes on creation. */ + r1.hash = r2.hash = 42; + struct rule r3 = { + .prev = &r2, + .prio = 'E', + .hash = 42, + .tag = "ASD", + .limit = 0, + }, r4 = { + .prev = &r3, + .prio = 'F', + .hash = 42, + .tag = "ZXC", + .limit = 0, + }; + + __log_limiter_destroy(); + __log_limiter_initialize(&r3); + + struct rule r5 = { + .prev = &r4, + .prio = 'E', + .hash = 69, + .tag = "ZAQ", + .limit = 0, + }, r6 = { + .prev = &r5, + .prio = 'D', + .hash = 69, + .tag = "WSX", + .limit = 0, + }; + + __log_limiter_destroy(); + __log_limiter_initialize(&r5); + log_config_free(&conf); __log_limiter_destroy(); } -- 2.7.4