diff --git a/CMakeLists.txt b/CMakeLists.txt index 23e6a47..c2bcbd4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,9 @@ add_library(webfused-static STATIC src/webfused/auth/authenticator.c src/webfused/auth/factory.c src/webfused/auth/file_authenticator.c + src/webfused/log/log.c src/webfused/log/logger.c + src/webfused/log/manager.c src/webfused/log/stderr_logger.c src/webfused/log/syslog_logger.c ) @@ -124,6 +126,9 @@ add_executable(alltests test/test_file_authenticator.cc test/test_mountpoint_factory.cc test/test_log.cc + test/test_log_manager.cc + test/test_stderr_logger.cc + test/test_syslog_logger.cc ) target_include_directories(alltests PRIVATE @@ -137,7 +142,9 @@ target_compile_options(alltests PRIVATE ${GMOCK_CFLAGS} ${GTEST_CFLAGS} "-pthrea target_link_libraries(alltests PRIVATE -Wl,--wrap=wf_credentials_type -Wl,--wrap=wf_credentials_get - -Wl,--wrap=wfd_settings_get + -Wl,--wrap=wfd_settings_get_string + -Wl,--wrap=wfd_settings_get_string_or_default + -Wl,--wrap=wfd_settings_get_bool webfused-static userdb ${LIBCONFIG_LIBRARIES} diff --git a/src/webfused/auth/file_authenticator.c b/src/webfused/auth/file_authenticator.c index afc64dd..61dae0a 100644 --- a/src/webfused/auth/file_authenticator.c +++ b/src/webfused/auth/file_authenticator.c @@ -76,7 +76,7 @@ wfd_file_authenticator_create( { bool result = false; - char const * filename = wfd_settings_get(settings, "file"); + char const * filename = wfd_settings_get_string(settings, "file"); if (NULL != filename) { struct wfd_file_authenticator * data = malloc(sizeof(struct wfd_file_authenticator)); diff --git a/src/webfused/config/builder.c b/src/webfused/config/builder.c index bbe7680..6d712f4 100644 --- a/src/webfused/config/builder.c +++ b/src/webfused/config/builder.c @@ -58,4 +58,15 @@ wfd_config_builder_add_filesystem( return builder.vtable->add_filesystem(builder.data, name, mount_point); } +bool +wfd_config_builder_set_logger( + struct wfd_config_builder builder, + char const * provider, + int level, + struct wfd_settings * settings) +{ + return builder.vtable->set_logger(builder.data, provider, level, settings); +} + + diff --git a/src/webfused/config/builder.h b/src/webfused/config/builder.h index ccb80ed..01348ea 100644 --- a/src/webfused/config/builder.h +++ b/src/webfused/config/builder.h @@ -49,6 +49,13 @@ wfd_config_builder_add_filesystem_fn( char const * name, char const * mount_point); +typedef bool +wfd_config_builder_set_logger_fn( + void * data, + char const * provider, + int level, + struct wfd_settings * settings); + struct wfd_config_builder_vtable { wfd_config_builder_set_server_vhostname_fn * set_server_vhostname; @@ -58,6 +65,7 @@ struct wfd_config_builder_vtable wfd_config_builder_set_server_document_root_fn * set_server_document_root; wfd_config_builder_add_auth_provider_fn * add_auth_provider; wfd_config_builder_add_filesystem_fn * add_filesystem; + wfd_config_builder_set_logger_fn * set_logger; }; struct wfd_config_builder @@ -103,6 +111,13 @@ wfd_config_builder_add_filesystem( char const * name, char const * mount_point); +extern bool +wfd_config_builder_set_logger( + struct wfd_config_builder builder, + char const * provider, + int level, + struct wfd_settings * settings); + #ifdef __cplusplus } #endif diff --git a/src/webfused/config/config.c b/src/webfused/config/config.c index f8e45f1..f74fed7 100644 --- a/src/webfused/config/config.c +++ b/src/webfused/config/config.c @@ -3,6 +3,7 @@ #include "webfused/auth/factory.h" #include "webfused/auth/authenticator.h" #include "webfused/mountpoint_factory.h" +#include "webfused/log/manager.h" #include @@ -100,6 +101,17 @@ wfd_config_add_filesystem( config->mountpoint_factory, name, mount_point); } +static bool +wfd_config_set_logger( + void * data, + char const * provider, + int level, + struct wfd_settings * settings) +{ + struct wfd_config * config = data; + return wfd_log_manager_set_logger(provider, level, settings); +} + static const struct wfd_config_builder_vtable wfd_config_vtable_config_builder = { @@ -109,7 +121,8 @@ wfd_config_vtable_config_builder = .set_server_cert = &wfd_config_set_server_cert, .set_server_document_root = &wfd_config_set_server_document_root, .add_auth_provider = &wfd_config_add_auth_provider, - .add_filesystem = &wfd_config_add_filesystem + .add_filesystem = &wfd_config_add_filesystem, + .set_logger = &wfd_config_set_logger }; struct wfd_config * diff --git a/src/webfused/config/factory.c b/src/webfused/config/factory.c index 2f3c36f..ddd4ff0 100644 --- a/src/webfused/config/factory.c +++ b/src/webfused/config/factory.c @@ -55,6 +55,59 @@ wfd_config_check_version( return true; } +static bool +wfd_config_read_logger( + config_t * config, + struct wfd_config_builder builder) +{ + bool result = true; + + bool hasLogger = (NULL != config_lookup(config, "log")); + if (hasLogger) + { + char const * provider; + int rc = config_lookup_string(config, "log.provider", &provider); + if (CONFIG_TRUE != rc) + { + WFD_ERROR("missing log provider"); + result = false; + } + + char const * level_str; + if (result) + { + rc = config_lookup_string(config, "log.level", &level_str); + if (CONFIG_TRUE != rc) + { + WFD_ERROR("missing log level"); + result = false; + } + } + + int level; + if (result) + { + bool success = wfd_log_level_parse(level_str, &level); + if (!success) + { + WFD_ERROR("failed to parse log level: unknown valuie \'%s\'", level_str); + result = false; + } + } + + if (result) + { + config_setting_t * setting = config_lookup(config, "log.settings"); + struct wfd_settings settings; + wfd_settings_init(&settings, setting); + result = wfd_config_builder_set_logger(builder, provider, level, &settings); + wfd_settings_cleanup(&settings); + } + } + + return result; +} + static bool wfd_config_read_server( config_t * config, @@ -198,6 +251,7 @@ wfd_config_load( { bool result = wfd_config_check_version(config) + && wfd_config_read_logger(config, builder) && wfd_config_read_server(config, builder) && wfd_config_read_authentication(config, builder) && wfd_config_read_filesystems(config, builder) diff --git a/src/webfused/config/settings.c b/src/webfused/config/settings.c index cafec21..0c7df95 100644 --- a/src/webfused/config/settings.c +++ b/src/webfused/config/settings.c @@ -20,13 +20,41 @@ wfd_settings_cleanup( } char const * -wfd_settings_get( +wfd_settings_get_string( struct wfd_settings * settings, char const * key) { + if (NULL == settings) {return NULL; } + char const * result; int rc = config_setting_lookup_string(settings->setting, key, &result); return (CONFIG_TRUE == rc) ? result : NULL; } +char const * +wfd_settings_get_string_or_default( + struct wfd_settings * settings, + char const * key, + char const * default_value) +{ + if (NULL == settings) {return default_value; } + + char const * result; + int rc = config_setting_lookup_string(settings->setting, key, &result); + + return (CONFIG_TRUE == rc) ? result : default_value; +} + +bool +wfd_settings_get_bool( + struct wfd_settings * settings, + char const * key) +{ + if (NULL == settings) {return false; } + + int result; + int rc = config_setting_lookup_bool(settings->setting, key, &result); + + return ((CONFIG_TRUE == rc) && (CONFIG_TRUE == result)); +} diff --git a/src/webfused/config/settings.h b/src/webfused/config/settings.h index f89b23b..9035367 100644 --- a/src/webfused/config/settings.h +++ b/src/webfused/config/settings.h @@ -1,6 +1,10 @@ #ifndef WFD_CONFIG_SETTINGS_H #define WFD_CONFIG_SETTINGS_H +#ifndef __cplusplus +#include +#endif + #ifdef __cplusplus extern "C" { @@ -10,7 +14,18 @@ struct wfd_settings; extern char const * -wfd_settings_get( +wfd_settings_get_string( + struct wfd_settings * settings, + char const * key); + +extern char const * +wfd_settings_get_string_or_default( + struct wfd_settings * settings, + char const * key, + char const * default_value); + +extern bool +wfd_settings_get_bool( struct wfd_settings * settings, char const * key); diff --git a/src/webfused/daemon.c b/src/webfused/daemon.c index 457b1fe..b7786cd 100644 --- a/src/webfused/daemon.c +++ b/src/webfused/daemon.c @@ -98,7 +98,7 @@ static void on_interrupt(int signal_id) int wfd_daemon_run(int argc, char * argv[]) { - wfd_stderr_logger_init(WFD_LOGLEVEL_ALL); + wfd_stderr_logger_init(WFD_LOGLEVEL_ALL, NULL); struct args args; int result = parse_arguments(argc, argv, &args); diff --git a/src/webfused/log/log.c b/src/webfused/log/log.c new file mode 100644 index 0000000..986fa5f --- /dev/null +++ b/src/webfused/log/log.c @@ -0,0 +1,62 @@ +#include "webfused/log/log.h" +#include + +char const * +wfd_log_level_tostring(int level) +{ + switch (level) + { + case WFD_LOGLEVEL_NONE: return "none"; + case WFD_LOGLEVEL_FATAL: return "fatal"; + case WFD_LOGLEVEL_ERROR: return "error"; + case WFD_LOGLEVEL_WARN: return "warn"; + case WFD_LOGLEVEL_INFO: return "info"; + case WFD_LOGLEVEL_DEBUG: return "debug"; + case WFD_LOGLEVEL_ALL: return "all"; + default: return ""; + } +} + +bool +wfd_log_level_parse( + char const * level, + int * result) +{ + bool success = true; + + if (0 == strcasecmp("all", level)) + { + *result = WFD_LOGLEVEL_ALL; + } + else if (0 == strcasecmp("none", level)) + { + *result = WFD_LOGLEVEL_NONE; + } + else if (0 == strcasecmp("fatal", level)) + { + *result = WFD_LOGLEVEL_FATAL; + } + else if (0 == strcasecmp("error", level)) + { + *result = WFD_LOGLEVEL_ERROR; + } + else if ((0 == strcasecmp("warn", level)) || + (0 == strcasecmp("warning", level))) + { + *result = WFD_LOGLEVEL_WARN; + } + else if (0 == strcasecmp("info", level)) + { + *result = WFD_LOGLEVEL_INFO; + } + else if (0 == strcasecmp("debug", level)) + { + *result = WFD_LOGLEVEL_DEBUG; + } + else + { + return false; + } + + return success; +} diff --git a/src/webfused/log/log.h b/src/webfused/log/log.h index 08a3b54..3a312c1 100644 --- a/src/webfused/log/log.h +++ b/src/webfused/log/log.h @@ -2,6 +2,7 @@ #define WFD_LOG_H #ifndef __cplusplus +#include #include #else #include @@ -16,6 +17,7 @@ extern "C" #define WFD_LOGLEVEL WFD_LOGLEVEL_ALL #endif +#define WFD_LOGLEVEL_NONE -1 #define WFD_LOGLEVEL_FATAL 1 #define WFD_LOGLEVEL_ERROR 3 #define WFD_LOGLEVEL_WARN 4 @@ -51,6 +53,14 @@ wfd_log( char const * format, ...); +extern char const * +wfd_log_level_tostring(int level); + +extern bool +wfd_log_level_parse( + char const * level, + int * result); + #ifdef __cplusplus } #endif diff --git a/src/webfused/log/manager.c b/src/webfused/log/manager.c new file mode 100644 index 0000000..c8f09b0 --- /dev/null +++ b/src/webfused/log/manager.c @@ -0,0 +1,30 @@ +#include "webfused/log/manager.h" +#include "webfused/log/log.h" +#include "webfused/log/stderr_logger.h" +#include "webfused/log/syslog_logger.h" + +#include + +bool +wfd_log_manager_set_logger( + char const * provider, + int level, + struct wfd_settings * settings) +{ + bool result = false; + + if (0 == strcmp("syslog", provider)) + { + result = wfd_syslog_logger_init(level, settings); + } + else if (0 == strcmp("stderr", provider)) + { + result = wfd_stderr_logger_init(level, settings); + } + else + { + WFD_ERROR("failed to init log: unknown provider \'%s\'", provider); + } + + return result; +} diff --git a/src/webfused/log/manager.h b/src/webfused/log/manager.h new file mode 100644 index 0000000..103418f --- /dev/null +++ b/src/webfused/log/manager.h @@ -0,0 +1,25 @@ +#ifndef WFD_LOG_MANAGER_H +#define WFD_LOG_MANAGER_H + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wfd_settings; + +extern bool +wfd_log_manager_set_logger( + char const * provider, + int level, + struct wfd_settings * settings); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/webfused/log/stderr_logger.c b/src/webfused/log/stderr_logger.c index 224f7f9..34c3f5f 100644 --- a/src/webfused/log/stderr_logger.c +++ b/src/webfused/log/stderr_logger.c @@ -5,36 +5,25 @@ #include #include -static const char * -wfd_stderr_logger_level_str(int level) -{ - switch (level) - { - case WFD_LOGLEVEL_FATAL: return "fatal"; - case WFD_LOGLEVEL_ERROR: return "error"; - case WFD_LOGLEVEL_WARN: return "warn"; - case WFD_LOGLEVEL_INFO: return "info"; - case WFD_LOGLEVEL_DEBUG: return "debug"; - default: return "notice"; - } -} - -void +static void wfd_stderr_logger_log( void * user_data, int level, char const * format, va_list args) { - fprintf(stderr, "%s: ", wfd_stderr_logger_level_str(level)); + fprintf(stderr, "%s: ", wfd_log_level_tostring(level)); vfprintf(stderr, format, args); fprintf(stderr, "\n"); } - -void +bool wfd_stderr_logger_init( - int level) + int level, + struct wfd_settings * settings) { + (void) settings; + wfd_logger_init(level, &wfd_stderr_logger_log, NULL, NULL); + return true; } diff --git a/src/webfused/log/stderr_logger.h b/src/webfused/log/stderr_logger.h index 40385da..d1bb25e 100644 --- a/src/webfused/log/stderr_logger.h +++ b/src/webfused/log/stderr_logger.h @@ -2,9 +2,7 @@ #define WFD_LOG_STDERR_LOGGER_H #ifndef __cplusplus -#include -#else -#include +#include #endif #ifdef __cplusplus @@ -12,17 +10,12 @@ extern "C" { #endif -extern void -wfd_stderr_logger_log( - void * user_data, - int level, - char const * format, - va_list args); - +struct wfd_settings; -extern void +extern bool wfd_stderr_logger_init( - int level); + int level, + struct wfd_settings * settings); #ifdef __cplusplus } diff --git a/src/webfused/log/syslog_logger.c b/src/webfused/log/syslog_logger.c index 02bca99..0f66ad4 100644 --- a/src/webfused/log/syslog_logger.c +++ b/src/webfused/log/syslog_logger.c @@ -1,8 +1,11 @@ #include "webfused/log/syslog_logger.h" #include "webfused/log/logger.h" #include "webfused/log/log.h" +#include "webfused/config/settings.h" #include +#include + #include static int @@ -40,17 +43,80 @@ wfd_syslog_logger_close( closelog(); } -void +struct wfd_syslog_facility +{ + char const * name; + int value; +}; + +static bool +wfd_syslog_logger_parse_facility( + char const * facility, + int * result) +{ + static struct wfd_syslog_facility const facilities[] = + { + {"auth", LOG_AUTH}, + {"authpriv", LOG_AUTHPRIV}, + {"cron", LOG_CRON}, + {"daemon", LOG_DAEMON}, + {"fpt", LOG_FTP}, + {"kern", LOG_KERN}, + {"local0", LOG_LOCAL0}, + {"local1", LOG_LOCAL1}, + {"local2", LOG_LOCAL2}, + {"local3", LOG_LOCAL3}, + {"local4", LOG_LOCAL4}, + {"local5", LOG_LOCAL5}, + {"local6", LOG_LOCAL6}, + {"local7", LOG_LOCAL7}, + {"lpr", LOG_LPR}, + {"mail", LOG_MAIL}, + {"news", LOG_NEWS}, + {"syslog", LOG_SYSLOG}, + {"user", LOG_USER}, + {"uucp", LOG_UUCP} + }; + static size_t const facilites_count = sizeof(facilities) / sizeof(facilities[0]); + + for (size_t i = 0; i < facilites_count; i++) + { + if (0 == strcasecmp(facility, facilities[i].name)) + { + *result = facilities[i].value; + return true; + } + } + + return false; +} + + +bool wfd_syslog_logger_init( int level, - char const * ident, - int options, - int facility) + struct wfd_settings * settings) { - wfd_logger_init(level, - &wfd_syslog_logger_log, - &wfd_syslog_logger_close, - NULL); + char const * ident = wfd_settings_get_string_or_default(settings, "ident", "webfused"); + char const * facility_str = wfd_settings_get_string_or_default(settings, "facility", "daemon"); + bool log_pid = wfd_settings_get_bool(settings, "log_pid"); + + int facility; + bool result = wfd_syslog_logger_parse_facility(facility_str, &facility); + if (result) + { + int options = (log_pid) ? LOG_PID : 0; + wfd_logger_init(level, + &wfd_syslog_logger_log, + &wfd_syslog_logger_close, + NULL); + + openlog(ident, options, facility); + } + else + { + WFD_ERROR("failed to init syslog logger: invalid log facility: \'%s\'", facility_str); + } - openlog(ident, options, facility); + return result; } \ No newline at end of file diff --git a/src/webfused/log/syslog_logger.h b/src/webfused/log/syslog_logger.h index 1466d1d..6682715 100644 --- a/src/webfused/log/syslog_logger.h +++ b/src/webfused/log/syslog_logger.h @@ -1,17 +1,21 @@ #ifndef WFD_LOG_SYSLOG_LOGGER_H #define WFD_LOG_SYSLOG_LOGGER_H +#ifndef __cplusplus +#include +#endif + #ifdef __cplusplus extern "C" { #endif -extern void +struct wfd_settings; + +extern bool wfd_syslog_logger_init( int level, - char const * ident, - int options, - int facility); + struct wfd_settings * settings); #ifdef __cplusplus } diff --git a/test/mock_config_builder.cc b/test/mock_config_builder.cc index c1ae9b8..7967178 100644 --- a/test/mock_config_builder.cc +++ b/test/mock_config_builder.cc @@ -69,6 +69,17 @@ wfd_MockConfigBuilder_add_filesystem( return builder->addFilesystem(name, mountpoint); } +static bool +wfd_MockConfigBuilder_set_logger( + void * data, + char const * provider, + int level, + struct wfd_settings * settings) +{ + auto * builder = reinterpret_cast(data); + return builder->setLogger(provider, level, settings); +} + static const wfd_config_builder_vtable wfd_MockConfigBuilder_vtable = { @@ -78,7 +89,8 @@ static const wfd_config_builder_vtable wfd_MockConfigBuilder_vtable = &wfd_MockConfigBuilder_set_server_cert, &wfd_MockConfigBuilder_set_server_document_root, &wfd_MockConfigBuilder_add_auth_provider, - &wfd_MockConfigBuilder_add_filesystem + &wfd_MockConfigBuilder_add_filesystem, + &wfd_MockConfigBuilder_set_logger }; } diff --git a/test/mock_config_builder.hpp b/test/mock_config_builder.hpp index f0c04a6..a512a10 100644 --- a/test/mock_config_builder.hpp +++ b/test/mock_config_builder.hpp @@ -18,6 +18,7 @@ public: virtual void setServerDocumentRoot(char const * document_root) = 0; virtual bool addAuthProvider(char const * provider, wfd_settings * settings) = 0; virtual bool addFilesystem(char const * name, char const * mountpoint) = 0; + virtual bool setLogger(char const * provider, int level, wfd_settings * settings) = 0; }; class MockConfigBuilder: public IConfigBuilder @@ -31,6 +32,7 @@ public: MOCK_METHOD1(setServerDocumentRoot, void (char const * document_root)); MOCK_METHOD2(addAuthProvider, bool (char const * provider, wfd_settings * settings)); MOCK_METHOD2(addFilesystem, bool (char const * name, char const * mountpoint)); + MOCK_METHOD3(setLogger, bool (char const * provider, int level, wfd_settings * settings)); struct wfd_config_builder getBuilder(); }; diff --git a/test/mock_settings.cc b/test/mock_settings.cc index cc66555..3cc36ff 100644 --- a/test/mock_settings.cc +++ b/test/mock_settings.cc @@ -7,25 +7,67 @@ using webfused_test::ISettings; static ISettings * wfd_mock_settings = nullptr; extern char const * -__real_wfd_settings_get( +__real_wfd_settings_get_string( + struct wfd_settings * settings, + char const * key); + +extern char const * +__real_wfd_settings_get_string_or_default( + struct wfd_settings * settings, + char const * key, + char const * default_value); + +extern bool +__real_wfd_settings_get_bool( struct wfd_settings * settings, char const * key); char const * -__wrap_wfd_settings_get( +__wrap_wfd_settings_get_string( struct wfd_settings * settings, char const * key) { if (nullptr == wfd_mock_settings) { - return __real_wfd_settings_get(settings, key); + return __real_wfd_settings_get_string(settings, key); } else { - return wfd_mock_settings->get(key); + return wfd_mock_settings->getString(key); } } +char const * +__wrap_wfd_settings_get_string_or_default( + struct wfd_settings * settings, + char const * key, + char const * default_value) +{ + if (nullptr == wfd_mock_settings) + { + return __real_wfd_settings_get_string_or_default( + settings, key, default_value); + } + else + { + return wfd_mock_settings->getStringOrDefault(key, default_value); + } +} + +bool +__wrap_wfd_settings_get_bool( + struct wfd_settings * settings, + char const * key) +{ + if (nullptr == wfd_mock_settings) + { + return __real_wfd_settings_get_bool(settings, key); + } + else + { + return wfd_mock_settings->getBool(key); + } +} } diff --git a/test/mock_settings.hpp b/test/mock_settings.hpp index 016a8f4..f3d8692 100644 --- a/test/mock_settings.hpp +++ b/test/mock_settings.hpp @@ -11,7 +11,9 @@ class ISettings { public: virtual ~ISettings() = default; - virtual char const * get(char const * key) = 0; + virtual char const * getString(char const * key) = 0; + virtual char const * getStringOrDefault(char const * key, char const * default_value) = 0; + virtual bool getBool(char const * key) = 0; }; class MockSettings: public ISettings @@ -19,7 +21,9 @@ class MockSettings: public ISettings public: MockSettings(); ~MockSettings() override; - MOCK_METHOD1(get, char const * (char const * key)); + MOCK_METHOD1(getString, char const * (char const * key)); + MOCK_METHOD2(getStringOrDefault, char const * (char const * key, char const * default_value)); + MOCK_METHOD1(getBool, bool (char const * key)); }; } diff --git a/test/test_config.cc b/test/test_config.cc index 14df533..4fe66be 100644 --- a/test/test_config.cc +++ b/test/test_config.cc @@ -38,7 +38,7 @@ TEST(config, auth_config) wfd_config_builder builder = wfd_config_get_builder(config); MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); bool success = wfd_config_builder_add_auth_provider(builder, "file", nullptr); ASSERT_TRUE(success); @@ -54,7 +54,7 @@ TEST(config, auth_config_failed_to_add_second_provider) wfd_config_builder builder = wfd_config_get_builder(config); MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); bool success = wfd_config_builder_add_auth_provider(builder, "file", nullptr); ASSERT_TRUE(success); @@ -88,5 +88,18 @@ TEST(config, add_filesystem) bool success = wfd_config_builder_add_filesystem(builder, "test", "/tmp/test"); ASSERT_TRUE(success); + wfd_config_dispose(config); +} + +TEST(config, set_logger) +{ + wfd_config * config = wfd_config_create(); + ASSERT_NE(nullptr, config); + + wfd_config_builder builder = wfd_config_get_builder(config); + + bool success = wfd_config_builder_set_logger(builder, "stderr", WFD_LOGLEVEL_ALL, nullptr); + ASSERT_TRUE(success); + wfd_config_dispose(config); } \ No newline at end of file diff --git a/test/test_config_factory.cc b/test/test_config_factory.cc index 374af8c..58d2f7d 100644 --- a/test/test_config_factory.cc +++ b/test/test_config_factory.cc @@ -17,6 +17,7 @@ using ::webfused_test::MockConfigBuilder; TEST(config, is_loadable) { StrictMock builder; + EXPECT_CALL(builder, setLogger(_,_,_)).Times(1).WillOnce(Return(true)); EXPECT_CALL(builder, setServerVhostname(StrEq("localhost"))).Times(1); EXPECT_CALL(builder, setServerPort(8080)).Times(1); EXPECT_CALL(builder, addAuthProvider(_, _)).Times(1).WillOnce(Return(true)); @@ -433,3 +434,107 @@ TEST(config, filesystems_failed_missing_mountpoint) bool result = wfd_config_load_string(builder.getBuilder(), config_text); ASSERT_FALSE(result); } + +TEST(config, log) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, setLogger(_, _, _)).Times(1).WillOnce(Return(true)); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "log:\n" + "{\n" + " provider = \"stderr\"\n" + " level = \"all\"\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_TRUE(result); +} + +TEST(config, log_fail_set_logger) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, setLogger(_, _, _)).Times(1).WillOnce(Return(false)); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "log:\n" + "{\n" + " provider = \"stderr\"\n" + " level = \"all\"\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + +TEST(config, log_fail_missing_provider) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, setLogger(_, _, _)).Times(0); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "log:\n" + "{\n" + " level = \"all\"\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + +TEST(config, log_fail_missing_level) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, setLogger(_, _, _)).Times(0); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "log:\n" + "{\n" + " provider = \"stderr\"\n" + " level = \"fancy\"\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + +TEST(config, log_fail_invalid_level) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, setLogger(_, _, _)).Times(0); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "log:\n" + "{\n" + " provider = \"stderr\"\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + diff --git a/test/test_file_authenticator.cc b/test/test_file_authenticator.cc index 451b4fa..ff3293e 100644 --- a/test/test_file_authenticator.cc +++ b/test/test_file_authenticator.cc @@ -17,7 +17,7 @@ using ::testing::StrEq; TEST(file_authenticator, create) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -29,7 +29,7 @@ TEST(file_authenticator, create) TEST(file_authenticator, create_fail_missing_file) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return(nullptr)); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return(nullptr)); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -39,7 +39,7 @@ TEST(file_authenticator, create_fail_missing_file) TEST(file_authenticator, create_via_factory) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; bool success = wfd_authenticator_create("file", nullptr, &authenticator); @@ -51,7 +51,7 @@ TEST(file_authenticator, create_via_factory) TEST(file_authenticator, authenticate) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -70,7 +70,7 @@ TEST(file_authenticator, authenticate) TEST(file_authenticator, authenticate_fail_wrong_passwd) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -89,7 +89,7 @@ TEST(file_authenticator, authenticate_fail_wrong_passwd) TEST(file_authenticator, authenticate_fail_no_passwd_file) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("unknown_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("unknown_passwd.json")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -108,7 +108,7 @@ TEST(file_authenticator, authenticate_fail_no_passwd_file) TEST(file_authenticator, authenticate_fail_missing_username) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -127,7 +127,7 @@ TEST(file_authenticator, authenticate_fail_missing_username) TEST(file_authenticator, authenticate_fail_missing_password) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -146,7 +146,7 @@ TEST(file_authenticator, authenticate_fail_missing_password) TEST(file_authenticator, get_type) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); diff --git a/test/test_log.cc b/test/test_log.cc index 86423bb..331d0eb 100644 --- a/test/test_log.cc +++ b/test/test_log.cc @@ -108,4 +108,63 @@ TEST(log, omit_onclose_if_nullptr) TEST(log, default_log) { WFD_ERROR("trigger log"); +} + +TEST(log, loglevel_parse) +{ + int level; + + ASSERT_TRUE(wfd_log_level_parse("fatal", &level)); + ASSERT_EQ(WFD_LOGLEVEL_FATAL, level); + ASSERT_TRUE(wfd_log_level_parse("FATAL", &level)); + ASSERT_EQ(WFD_LOGLEVEL_FATAL, level); + + ASSERT_TRUE(wfd_log_level_parse("error", &level)); + ASSERT_EQ(WFD_LOGLEVEL_ERROR, level); + ASSERT_TRUE(wfd_log_level_parse("ERROR", &level)); + ASSERT_EQ(WFD_LOGLEVEL_ERROR, level); + + ASSERT_TRUE(wfd_log_level_parse("warn", &level)); + ASSERT_EQ(WFD_LOGLEVEL_WARN, level); + ASSERT_TRUE(wfd_log_level_parse("WARN", &level)); + ASSERT_EQ(WFD_LOGLEVEL_WARN, level); + ASSERT_TRUE(wfd_log_level_parse("warning", &level)); + ASSERT_EQ(WFD_LOGLEVEL_WARN, level); + ASSERT_TRUE(wfd_log_level_parse("WARNING", &level)); + ASSERT_EQ(WFD_LOGLEVEL_WARN, level); + + ASSERT_TRUE(wfd_log_level_parse("info", &level)); + ASSERT_EQ(WFD_LOGLEVEL_INFO, level); + ASSERT_TRUE(wfd_log_level_parse("INFO", &level)); + ASSERT_EQ(WFD_LOGLEVEL_INFO, level); + + ASSERT_TRUE(wfd_log_level_parse("debug", &level)); + ASSERT_EQ(WFD_LOGLEVEL_DEBUG, level); + ASSERT_TRUE(wfd_log_level_parse("DEBUG", &level)); + ASSERT_EQ(WFD_LOGLEVEL_DEBUG, level); + + ASSERT_FALSE(wfd_log_level_parse("", &level)); + + ASSERT_TRUE(wfd_log_level_parse("all", &level)); + ASSERT_EQ(WFD_LOGLEVEL_ALL, level); + ASSERT_TRUE(wfd_log_level_parse("ALL", &level)); + ASSERT_EQ(WFD_LOGLEVEL_ALL, level); + + ASSERT_TRUE(wfd_log_level_parse("none", &level)); + ASSERT_EQ(WFD_LOGLEVEL_NONE, level); + ASSERT_TRUE(wfd_log_level_parse("NONE", &level)); + ASSERT_EQ(WFD_LOGLEVEL_NONE, level); + +} + +TEST(log, log_level_tostring) +{ + ASSERT_STREQ("none", wfd_log_level_tostring(WFD_LOGLEVEL_NONE)); + ASSERT_STREQ("fatal", wfd_log_level_tostring(WFD_LOGLEVEL_FATAL)); + ASSERT_STREQ("error", wfd_log_level_tostring(WFD_LOGLEVEL_ERROR)); + ASSERT_STREQ("warn", wfd_log_level_tostring(WFD_LOGLEVEL_WARN)); + ASSERT_STREQ("info", wfd_log_level_tostring(WFD_LOGLEVEL_INFO)); + ASSERT_STREQ("debug", wfd_log_level_tostring(WFD_LOGLEVEL_DEBUG)); + ASSERT_STREQ("all", wfd_log_level_tostring(WFD_LOGLEVEL_ALL)); + ASSERT_STREQ("", wfd_log_level_tostring(42)); } \ No newline at end of file diff --git a/test/test_log_manager.cc b/test/test_log_manager.cc new file mode 100644 index 0000000..35ce8bb --- /dev/null +++ b/test/test_log_manager.cc @@ -0,0 +1,10 @@ +#include "webfused/log/manager.h" +#include "webfused/log/log.h" + +#include +#include + +TEST(log_manager, set_logger_fail_unknown_provider) +{ + ASSERT_FALSE(wfd_log_manager_set_logger("unknown", WFD_LOGLEVEL_ALL, NULL)); +} diff --git a/test/test_settings.cc b/test/test_settings.cc index 730a059..3f6b1a5 100644 --- a/test/test_settings.cc +++ b/test/test_settings.cc @@ -3,7 +3,7 @@ #include "webfused/config/settings.h" #include -TEST(settings, settings) +TEST(settings, get_string) { char const settings_text[] = "settings:\n" @@ -22,9 +22,68 @@ TEST(settings, settings) wfd_settings settings; wfd_settings_init(&settings, setting); - ASSERT_STREQ("some.string", wfd_settings_get(&settings, "string_value")); - ASSERT_EQ(nullptr, wfd_settings_get(&settings, "int_value")); - ASSERT_EQ(nullptr, wfd_settings_get(&settings, "invalid_value")); + ASSERT_STREQ("some.string", wfd_settings_get_string(&settings, "string_value")); + ASSERT_EQ(nullptr, wfd_settings_get_string(&settings, "int_value")); + ASSERT_EQ(nullptr, wfd_settings_get_string(&settings, "invalid_value")); + ASSERT_EQ(nullptr, wfd_settings_get_string(NULL, "invalid_value")); + + wfd_settings_cleanup(&settings); + config_destroy(&config); +} + +TEST(settings, get_string_or_default) +{ + char const settings_text[] = + "settings:\n" + "{\n" + " string_value = \"some.string\"\n" + " int_value = 42\n" + "}\n" + ; + config_t config; + config_init(&config); + int rc = config_read_string(&config, settings_text); + ASSERT_TRUE(CONFIG_TRUE == rc); + + config_setting_t * setting = config_lookup(&config, "settings"); + ASSERT_NE(nullptr, setting); + + wfd_settings settings; + wfd_settings_init(&settings, setting); + ASSERT_STREQ("some.string", wfd_settings_get_string_or_default(&settings, "string_value", "default")); + ASSERT_STREQ("default", wfd_settings_get_string_or_default(&settings, "int_value", "default")); + ASSERT_STREQ("default", wfd_settings_get_string_or_default(&settings, "invalid_value", "default")); + ASSERT_STREQ("default", wfd_settings_get_string_or_default(NULL, "invalid_value", "default")); + + wfd_settings_cleanup(&settings); + config_destroy(&config); +} + +TEST(settings, get_bool) +{ + char const settings_text[] = + "settings:\n" + "{\n" + " true_value = true\n" + " false_value = false\n" + " int_value = 42\n" + "}\n" + ; + config_t config; + config_init(&config); + int rc = config_read_string(&config, settings_text); + ASSERT_TRUE(CONFIG_TRUE == rc); + + config_setting_t * setting = config_lookup(&config, "settings"); + ASSERT_NE(nullptr, setting); + + wfd_settings settings; + wfd_settings_init(&settings, setting); + ASSERT_TRUE(wfd_settings_get_bool(&settings, "true_value")); + ASSERT_FALSE(wfd_settings_get_bool(&settings, "false_value")); + ASSERT_FALSE(wfd_settings_get_bool(&settings, "int_value")); + ASSERT_FALSE(wfd_settings_get_bool(&settings, "invalid_value")); + ASSERT_FALSE(wfd_settings_get_bool(NULL, "invalid_value")); wfd_settings_cleanup(&settings); config_destroy(&config); diff --git a/test/test_stderr_logger.cc b/test/test_stderr_logger.cc new file mode 100644 index 0000000..923bf59 --- /dev/null +++ b/test/test_stderr_logger.cc @@ -0,0 +1,27 @@ +#include "webfused/log/stderr_logger.h" +#include "webfused/log/manager.h" +#include "webfused/log/logger.h" +#include "webfused/log/log.h" + +#include +#include + +TEST(stderr_logger, init) +{ + ASSERT_TRUE(wfd_stderr_logger_init(WFD_LOGLEVEL_ALL, NULL)); + wfd_logger_close(); +} + +TEST(stderr_logger, init_via_manager) +{ + ASSERT_TRUE(wfd_log_manager_set_logger("stderr", WFD_LOGLEVEL_ALL, NULL)); + wfd_logger_close(); +} + +TEST(stderr_logger, log) +{ + ASSERT_TRUE(wfd_stderr_logger_init(WFD_LOGLEVEL_ALL, NULL)); + WFD_INFO("some information"); + + wfd_logger_close(); +} \ No newline at end of file diff --git a/test/test_syslog_logger.cc b/test/test_syslog_logger.cc new file mode 100644 index 0000000..1d04740 --- /dev/null +++ b/test/test_syslog_logger.cc @@ -0,0 +1,45 @@ +#include "webfused/log/syslog_logger.h" +#include "webfused/log/manager.h" +#include "webfused/log/logger.h" +#include "webfused/log/log.h" + +#include "mock_settings.hpp" + +#include +#include + +using ::webfused_test::MockSettings; +using ::testing::StrEq; +using ::testing::_; +using ::testing::Return; + +TEST(syslog_logger, init) +{ + ASSERT_TRUE(wfd_syslog_logger_init(WFD_LOGLEVEL_ALL, NULL)); + wfd_logger_close(); +} + +TEST(syslog_logger, init_fail_invalid_facility) +{ + MockSettings settings; + EXPECT_CALL(settings, getStringOrDefault(StrEq("ident"), _)).Times(1).WillOnce(Return("webfused_test")); + EXPECT_CALL(settings, getStringOrDefault(StrEq("facility"), _)).Times(1).WillOnce(Return("invalid")); + EXPECT_CALL(settings, getBool(StrEq("log_pid"))).Times(1).WillOnce(Return(false)); + + wfd_settings * fake_settings = reinterpret_cast(0xDEADBEEF); + ASSERT_FALSE(wfd_syslog_logger_init(WFD_LOGLEVEL_ALL, fake_settings)); +} + +TEST(syslog_logger, init_via_manager) +{ + ASSERT_TRUE(wfd_log_manager_set_logger("syslog", WFD_LOGLEVEL_ALL, NULL)); + wfd_logger_close(); +} + +TEST(syslog_logger, log) +{ + ASSERT_TRUE(wfd_syslog_logger_init(WFD_LOGLEVEL_ALL, NULL)); + WFD_INFO("some information"); + + wfd_logger_close(); +} \ No newline at end of file