/* 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 . */ #include #define G_LOG_DOMAIN "Spice" #include #include #include "common/log.h" #define OTHER_LOG_DOMAIN "Other" #define LOG_OTHER_HELPER(suffix, level) \ G_GNUC_PRINTF(1, 2) \ static void G_PASTE(other_, suffix)(const gchar *format, ...) \ { \ va_list args; \ \ va_start (args, format); \ g_logv(OTHER_LOG_DOMAIN, 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) /* Checks that spice_warning() aborts after setting G_DEBUG=fatal-warnings */ static void test_spice_fatal_warning(void) { g_setenv("G_DEBUG", "fatal-warnings", TRUE); if (g_test_subprocess()) { spice_warning("spice_warning"); return; } g_test_trap_subprocess(NULL, 0, 0); g_test_trap_assert_failed(); g_test_trap_assert_stderr("*spice_warning*"); g_unsetenv("G_DEBUG"); } /* 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_critical("g_critical"); return; } g_test_trap_subprocess(NULL, 0, 0); g_test_trap_assert_passed(); g_test_trap_assert_stderr("*g_critical*"); } /* Checks that g_critical() aborts after setting G_DEBUG=fatal-criticals */ static void test_spice_fatal_g_critical(void) { g_setenv("G_DEBUG", "fatal-criticals", TRUE); if (g_test_subprocess()) { g_critical("g_critical"); return; } g_test_trap_subprocess(NULL, 0, 0); g_test_trap_assert_failed(); g_test_trap_assert_stderr("*g_critical*"); g_unsetenv("G_DEBUG"); } /* 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(); g_test_trap_assert_stderr("*test_spice_fatal_return_if_fail*"); } /* Checks that g_return_if_fail() does not abort by default */ static void test_spice_non_fatal_g_return_if_fail(void) { if (g_test_subprocess()) { g_return_if_fail(FALSE); return; } g_test_trap_subprocess(NULL, 0, 0); g_test_trap_assert_passed(); } /* 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) { if (g_test_subprocess()) { g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "*spice_warning"); spice_warning("spice_warning"); g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*spice_info"); spice_info("spice_info"); g_test_expect_message(G_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"); g_test_trap_assert_stdout_unmatched("*spice_info*"); g_test_trap_assert_stdout_unmatched("*spice_debug*"); g_test_trap_assert_stdout_unmatched("*g_info*"); g_test_trap_assert_stdout_unmatched("*g_debug*"); g_test_trap_assert_stdout_unmatched("*other_info*"); g_test_trap_assert_stdout_unmatched("*other_debug*"); } /* 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"); g_test_trap_assert_stdout_unmatched("*other_debug*"); g_test_trap_assert_stdout_unmatched("*other_info*"); } /* 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"); } /* Checks that spice_assert() aborts if condition fails */ static void test_spice_assert(void) { if (g_test_subprocess()) { spice_assert(1 == 2); return; } g_test_trap_subprocess(NULL, 0, 0); g_test_trap_assert_failed(); g_test_trap_assert_stderr("*assertion `1 == 2' failed*"); } /* Checks that spice_extra_assert() aborts if condition fails */ static void test_spice_extra_assert(void) { if (g_test_subprocess()) { spice_extra_assert(1 == 2); return; } g_test_trap_subprocess(NULL, 0, 0); g_test_trap_assert_failed(); g_test_trap_assert_stderr("*assertion `1 == 2' failed*"); } static void handle_sigabrt(int sig G_GNUC_UNUSED) { _Exit(1); } int main(int argc, char **argv) { GLogLevelFlags fatal_mask; /* prevents core generations as this could cause some issues/timeout * depending on system configuration */ signal(SIGABRT, handle_sigabrt); fatal_mask = (GLogLevelFlags)g_log_set_always_fatal((GLogLevelFlags) G_LOG_FATAL_MASK); g_test_init(&argc, &argv, NULL); /* Reset fatal mask set by g_test_init() as we don't want * warnings/criticals to be fatal by default since this is what some of the * test cases are going to test */ g_log_set_always_fatal(fatal_mask & G_LOG_LEVEL_MASK); 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-gcritical", test_spice_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); g_test_add_func("/spice-common/spice-assert", test_spice_assert); if (spice_extra_checks) { g_test_add_func("/spice-common/spice-extra-assert", test_spice_extra_assert); } return g_test_run(); }