This gives us a baseline of how the SPICE/glib integration is supposed to behave. --- tests/Makefile.am | 19 ++- tests/test-logging.c | 410 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 427 insertions(+), 2 deletions(-) create mode 100644 tests/test-logging.c diff --git a/tests/Makefile.am b/tests/Makefile.am index d612d44..52c0809 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,22 @@ NULL = -TESTS = test_marshallers -check_PROGRAMS = test_marshallers +TESTS = test_logging test_marshallers +check_PROGRAMS = $(TESTS) + +test_logging_SOURCES = test-logging.c +test_logging_CFLAGS = \ + -I$(top_srcdir) \ + $(GLIB2_CFLAGS) \ + $(GIO_UNIX_CFLAGS) \ + $(PROTOCOL_CFLAGS) \ + $(NULL) +test_logging_LDADD = \ + $(top_builddir)/common/libspice-common.la \ + $(GLIB2_LIBS) \ + $(GIO_UNIX_LIBS) \ + $(NULL) + + test_marshallers_SOURCES = \ generated_test_marshallers.c \ generated_test_marshallers.h \ diff --git a/tests/test-logging.c b/tests/test-logging.c new file mode 100644 index 0000000..cf05016 --- /dev/null +++ b/tests/test-logging.c @@ -0,0 +1,410 @@ +/* + Copyright (C) 2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#define G_LOG_DOMAIN "Spice" +#define SPICE_LOG_DOMAIN G_LOG_DOMAIN + +#include <glib.h> + +#include "common/log.h" + +#define OTHER_LOG_DOMAIN "Other" +#define LOG_OTHER_HELPER(suffix, level) \ + static void G_PASTE(other_, suffix)(const gchar *format, ...) \ + { \ + va_list args; \ + \ + va_start (args, format); \ + g_logv(OTHER_LOG_DOMAIN, G_PASTE(G_LOG_LEVEL_, level), format, args); \ + va_end (args); \ + } + +/* Set of helpers to log in a different log domain than "Spice" */ +LOG_OTHER_HELPER(debug, DEBUG) +LOG_OTHER_HELPER(info, INFO) +LOG_OTHER_HELPER(message, MESSAGE) +LOG_OTHER_HELPER(warning, WARNING) +LOG_OTHER_HELPER(critical, CRITICAL) + +/* Helper for use with g_test_log_set_fatal_handler() as uncaught + * warnings/criticals automatically cause test failures + */ +static gboolean non_fatal_warnings_criticals(const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + char *pattern = user_data; + + if ((log_level = G_LOG_LEVEL_WARNING) + && g_str_has_suffix(message, "_warning")) { + return FALSE; + } + if ((log_level = G_LOG_LEVEL_CRITICAL) + && g_str_has_suffix(message, "_critical")) { + return FALSE; + } + if (pattern != NULL) { + if (g_pattern_match_simple(pattern, message)) { + return FALSE; + } + } + + return TRUE; +} + + +/* Checks that spice_warning() aborts after changing SPICE_ABORT_LEVEL */ +static void test_spice_abort_level(void) +{ + if (g_test_subprocess()) { + /* 2 = SPICE_LOG_LEVEL_WARNING */ + g_setenv("SPICE_ABORT_LEVEL", "2", TRUE); + g_test_expect_message(NULL, + G_LOG_LEVEL_WARNING, + "*SPICE_ABORT_LEVEL*deprecated*"); + spice_debug("trigger deprecation warning"); + g_test_assert_expected_messages(); + spice_warning("spice_warning"); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_failed(); + g_test_trap_assert_stderr("*spice_warning*"); +} + +/* Checks that g_warning() aborts after changing SPICE_ABORT_LEVEL */ +static void test_spice_abort_level_g_warning(void) +{ + if (g_test_subprocess()) { + /* 2 = SPICE_LOG_LEVEL_WARNING */ + g_setenv("SPICE_ABORT_LEVEL", "2", TRUE); + g_test_expect_message(NULL, + G_LOG_LEVEL_WARNING, + "*SPICE_ABORT_LEVEL*deprecated*"); + spice_debug("trigger deprecation warning"); + g_test_assert_expected_messages(); + g_warning("g_warning"); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_failed(); + g_test_trap_assert_stderr("*g_warning*"); +} + +/* Checks that spice_warning() aborts after setting G_DEBUG=fatal-warnings */ +static void test_spice_fatal_warning(void) +{ + if (g_test_subprocess()) { + g_setenv("G_DEBUG", "fatal-warnings", TRUE); + spice_warning("spice_warning"); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_failed(); + g_test_trap_assert_stderr("*spice_warning*"); +} + +/* Checks that spice_critical() aborts by default */ +static void test_spice_fatal_critical(void) +{ + if (g_test_subprocess()) { + spice_critical("spice_critical"); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_failed(); + g_test_trap_assert_stderr("*spice_critical*"); +} + +/* Checks that g_critical() does not abort by default */ +static void test_spice_non_fatal_g_critical(void) +{ + if (g_test_subprocess()) { + g_test_expect_message(G_LOG_DOMAIN, + G_LOG_LEVEL_CRITICAL, + "*g_critical"); + g_critical("g_critical"); + g_test_assert_expected_messages(); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); +} + +/* Checks that spice_return_if_fail() aborts by default */ +static void test_spice_fatal_return_if_fail(void) +{ + if (g_test_subprocess()) { + spice_return_if_fail(FALSE); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_failed(); +} + +/* Checks that g_return_if_fail() does not abort by default */ +static void test_spice_non_fatal_g_return_if_fail(void) +{ + char *pattern = g_strconcat ("*", G_STRFUNC, "*", NULL); + g_test_log_set_fatal_handler(non_fatal_warnings_criticals, pattern); + + if (g_test_subprocess()) { + g_return_if_fail(FALSE); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); + g_free(pattern); +} + +/* Checks that spice_*, g_* and other_* (different log domain as g_*) all + * go through g_log() with the correct domain/log level. This then checks + * that only logs with level 'message' or higher are shown by default. + */ +static void test_log_levels(void) +{ + g_test_log_set_fatal_handler(non_fatal_warnings_criticals, NULL); + + if (g_test_subprocess()) { + g_test_expect_message(SPICE_LOG_DOMAIN, + G_LOG_LEVEL_WARNING, + "*spice_warning"); + spice_warning("spice_warning"); + g_test_expect_message(SPICE_LOG_DOMAIN, + G_LOG_LEVEL_INFO, + "*spice_info"); + spice_info("spice_info"); + g_test_expect_message(SPICE_LOG_DOMAIN, + G_LOG_LEVEL_DEBUG, + "*spice_debug"); + spice_debug("spice_debug"); + + g_test_expect_message(G_LOG_DOMAIN, + G_LOG_LEVEL_CRITICAL, + "*g_critical"); + g_critical("g_critical"); + g_test_expect_message(G_LOG_DOMAIN, + G_LOG_LEVEL_WARNING, + "*g_warning"); + g_warning("g_warning"); + g_test_expect_message(G_LOG_DOMAIN, + G_LOG_LEVEL_MESSAGE, + "*g_message"); + g_message("g_message"); + g_test_expect_message(G_LOG_DOMAIN, + G_LOG_LEVEL_INFO, + "*g_info"); + g_info("g_info"); + g_test_expect_message(G_LOG_DOMAIN, + G_LOG_LEVEL_DEBUG, + "*g_debug"); + g_debug("g_debug"); + + g_test_expect_message(OTHER_LOG_DOMAIN, + G_LOG_LEVEL_CRITICAL, + "*other_critical"); + other_critical("other_critical"); + g_test_expect_message(OTHER_LOG_DOMAIN, + G_LOG_LEVEL_WARNING, + "*other_warning"); + other_warning("other_warning"); + g_test_expect_message(OTHER_LOG_DOMAIN, + G_LOG_LEVEL_MESSAGE, + "*other_message"); + other_message("other_message"); + g_test_expect_message(OTHER_LOG_DOMAIN, + G_LOG_LEVEL_INFO, + "*other_info"); + other_info("other_info"); + g_test_expect_message(OTHER_LOG_DOMAIN, + G_LOG_LEVEL_DEBUG, + "*other_debug"); + other_debug("other_debug"); + + g_test_assert_expected_messages(); + + + /* g_test_expected_message only checks whether the appropriate messages got up to g_log() + * The following calls will be caught by the parent process to check what was (not) printed + * to stdout/stderr + */ + spice_warning("spice_warning"); + spice_info("spice_info"); + spice_debug("spice_debug"); + + g_critical("g_critical"); + g_warning("g_warning"); + g_message("g_message"); + g_info("g_info"); + g_debug("g_debug"); + + other_critical("other_critical"); + other_warning("other_warning"); + other_message("other_message"); + other_info("other_info"); + other_debug("other_debug"); + + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); + g_test_trap_assert_stderr("*spice_warning\n*g_critical\n*g_warning\n*g_message\n*other_critical\n*other_warning\n*other_message\n"); +} + +/* Checks that SPICE_DEBUG_LEVEL impacts spice_debug(), g_debug() but not other_debug() */ +static void test_spice_debug_level(void) +{ + if (g_test_subprocess()) { + g_setenv("SPICE_DEBUG_LEVEL", "5", TRUE); + g_test_expect_message(NULL, + G_LOG_LEVEL_WARNING, + "*SPICE_DEBUG_LEVEL*deprecated*"); + spice_debug("trigger deprecation warning"); + g_test_assert_expected_messages(); + + /* g_test_expected_message only checks whether the appropriate messages got up to g_log() + * The following calls will be caught by the parent process to check what was (not) printed + * to stdout/stderr + */ + spice_info("spice_info"); + g_debug("g_debug"); + spice_debug("spice_debug"); + other_debug("other_debug"); + + return; + } + + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); + g_test_trap_assert_stdout("*spice_info\n*g_debug\n*spice_debug\n"); +} + +/* Checks that raising SPICE_DEBUG_LEVEL allows to only show spice_warning() and spice_critical() + * messages, as well as g_warning() and g_critical(), but does not impact other_message() + */ +static void test_spice_debug_level_warning(void) +{ + g_test_log_set_fatal_handler(non_fatal_warnings_criticals, NULL); + + if (g_test_subprocess()) { + g_setenv("SPICE_ABORT_LEVEL", "0", TRUE); + g_setenv("SPICE_DEBUG_LEVEL", "1", TRUE); + g_test_expect_message(NULL, + G_LOG_LEVEL_WARNING, + "*SPICE_DEBUG_LEVEL*deprecated*"); + g_test_expect_message(NULL, + G_LOG_LEVEL_WARNING, + "*SPICE_ABORT_LEVEL*deprecated*"); + spice_debug("trigger deprecation warning"); + g_test_assert_expected_messages(); + + spice_info("spice_info"); + spice_debug("spice_debug"); + spice_warning("spice_warning"); + spice_critical("spice_critical"); + g_debug("g_debug"); + g_info("g_info"); + g_message("g_message"); + g_warning("g_warning"); + g_critical("g_critical"); + other_debug("other_debug"); + other_info("other_info"); + other_message("other_message"); + other_warning("other_warning"); + other_critical("other_critical"); + + return; + } + + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); + g_test_trap_assert_stderr("*spice_critical\n*g_critical\n*other_message\n*other_warning\n*other_critical\n"); +} + +/* Checks that setting G_MESSAGES_DEBUG to 'Spice' impacts spice_debug() and + * g_debug() but not other_debug() */ +static void test_spice_g_messages_debug(void) +{ + if (g_test_subprocess()) { + g_setenv("G_MESSAGES_DEBUG", "Spice", TRUE); + + spice_debug("spice_debug"); + spice_info("spice_info"); + g_debug("g_debug"); + g_info("g_info"); + g_message("g_message"); + other_debug("other_debug"); + other_info("other_info"); + other_message("other_message"); + + return; + } + + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); + g_test_trap_assert_stdout("*spice_debug\n*spice_info\n*g_debug\n*g_info\n"); + g_test_trap_assert_stderr("*g_message\n*other_message\n"); +} + +/* Checks that setting G_MESSAGES_DEBUG to 'all' impacts spice_debug(), + * g_debug() and other_debug() */ +static void test_spice_g_messages_debug_all(void) +{ + if (g_test_subprocess()) { + g_setenv("G_MESSAGES_DEBUG", "all", TRUE); + + spice_debug("spice_debug"); + spice_info("spice_info"); + g_debug("g_debug"); + g_info("g_info"); + g_message("g_message"); + other_debug("other_debug"); + other_info("other_info"); + other_message("other_message"); + + return; + } + + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); + g_test_trap_assert_stdout("*spice_debug\n*spice_info\n*g_debug\n*g_info\n*other_debug\n*other_info\n"); + g_test_trap_assert_stderr("*g_message\n*other_message\n"); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/spice-common/spice-abort-level", test_spice_abort_level); + g_test_add_func("/spice-common/spice-abort-level-gwarning", test_spice_abort_level_g_warning); + g_test_add_func("/spice-common/spice-debug-level", test_spice_debug_level); + g_test_add_func("/spice-common/spice-debug-level-warning", test_spice_debug_level_warning); + g_test_add_func("/spice-common/spice-g-messages-debug", test_spice_g_messages_debug); + g_test_add_func("/spice-common/spice-g-messages-debug-all", test_spice_g_messages_debug_all); + g_test_add_func("/spice-common/spice-log-levels", test_log_levels); + g_test_add_func("/spice-common/spice-fatal-critical", test_spice_fatal_critical); + g_test_add_func("/spice-common/spice-non-fatal-gcritical", test_spice_non_fatal_g_critical); + g_test_add_func("/spice-common/spice-fatal-return-if-fail", test_spice_fatal_return_if_fail); + g_test_add_func("/spice-common/spice-non-fatal-greturn-if-fail", test_spice_non_fatal_g_return_if_fail); + g_test_add_func("/spice-common/spice-fatal-warning", test_spice_fatal_warning); + + return g_test_run(); +} -- 2.5.0 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel