summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--glib/glib.symbols3
-rw-r--r--glib/gmessages.c47
-rw-r--r--glib/gtestutils.c1
-rw-r--r--glib/gtestutils.h21
-rw-r--r--glib/tests/testing.c27
5 files changed, 97 insertions, 2 deletions
diff --git a/glib/glib.symbols b/glib/glib.symbols
index 0a969806c..6e3a63b36 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -1332,6 +1332,9 @@ g_thread_pool_set_sort_function
#endif
#if IN_HEADER(__G_TEST_UTILS_H__)
+#if IN_FILE(__G_MESSAGES_C__)
+g_test_log_set_fatal_handler
+#endif
#if IN_FILE(__G_TEST_UTILS_C__)
g_assertion_message G_GNUC_NORETURN
g_assertion_message_cmpnum G_GNUC_NORETURN
diff --git a/glib/gmessages.c b/glib/gmessages.c
index e080ad6db..0f4bf4211 100644
--- a/glib/gmessages.c
+++ b/glib/gmessages.c
@@ -86,6 +86,8 @@ static GPrivate *g_log_depth = NULL;
static GLogLevelFlags g_log_msg_prefix = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_DEBUG;
static GLogFunc default_log_func = g_log_default_handler;
static gpointer default_log_data = NULL;
+static GTestLogFatalFunc fatal_log_func = NULL;
+static gpointer fatal_log_data;
/* --- functions --- */
#ifdef G_OS_WIN32
@@ -346,6 +348,39 @@ g_log_set_default_handler (GLogFunc log_func,
return old_log_func;
}
+/**
+ * g_test_log_set_fatal_handler:
+ * @log_func: the log handler function.
+ * @user_data: data passed to the log handler.
+ *
+ * Installs a non-error fatal log handler which can be
+ * used to decide whether log messages which are counted
+ * as fatal abort the program.
+ *
+ * The use case here is that you are running a test case
+ * that depends on particular libraries or circumstances
+ * and cannot prevent certain known critical or warning
+ * messages. So you install a handler that compares the
+ * domain and message to precisely not abort in such a case.
+ *
+ * Note that the handler is reset at the beginning of
+ * any test case, so you have to set it inside each test
+ * function which needs the special behavior.
+ *
+ * This handler has no effect on g_error messages.
+ *
+ * Since: 2.22
+ **/
+void
+g_test_log_set_fatal_handler (GTestLogFatalFunc log_func,
+ gpointer user_data)
+{
+ g_mutex_lock (g_messages_lock);
+ fatal_log_func = log_func;
+ fatal_log_data = user_data;
+ g_mutex_unlock (g_messages_lock);
+}
+
void
g_log_remove_handler (const gchar *log_domain,
guint handler_id)
@@ -456,6 +491,7 @@ g_logv (const gchar *log_domain,
}
}
+ gboolean masquerade_fatal = FALSE;
if (test_level & G_LOG_FLAG_RECURSION)
{
/* we use a stack buffer of fixed size, since we're likely
@@ -482,11 +518,18 @@ g_logv (const gchar *log_domain,
log_func (log_domain, test_level, msg, data);
+ if ((test_level & G_LOG_FLAG_FATAL)
+ && !(test_level & G_LOG_LEVEL_ERROR))
+ {
+ masquerade_fatal = fatal_log_func
+ && !fatal_log_func (log_domain, test_level, msg, data);
+ }
+
g_free (msg);
}
- if (test_level & G_LOG_FLAG_FATAL)
- {
+ if ((test_level & G_LOG_FLAG_FATAL) && !masquerade_fatal)
+ {
#ifdef G_OS_WIN32
gchar *locale_msg = g_locale_from_utf8 (fatal_msg_buf, -1, NULL, NULL, NULL);
diff --git a/glib/gtestutils.c b/glib/gtestutils.c
index 3f19fbc9a..fdb9494b8 100644
--- a/glib/gtestutils.c
+++ b/glib/gtestutils.c
@@ -1122,6 +1122,7 @@ test_case_run (GTestCase *tc)
void *fixture;
g_test_log (G_TEST_LOG_START_CASE, test_run_name, NULL, 0, NULL);
test_run_forks = 0;
+ g_test_log_set_fatal_handler (NULL, NULL);
g_timer_start (test_run_timer);
fixture = tc->fixture_size ? g_malloc0 (tc->fixture_size) : tc->test_data;
test_run_seed (test_run_seedstr);
diff --git a/glib/gtestutils.h b/glib/gtestutils.h
index 4c474589d..ac1ed28f1 100644
--- a/glib/gtestutils.h
+++ b/glib/gtestutils.h
@@ -262,6 +262,27 @@ void g_test_log_buffer_push (GTestLogBuffer *tbuffer,
GTestLogMsg* g_test_log_buffer_pop (GTestLogBuffer *tbuffer);
void g_test_log_msg_free (GTestLogMsg *tmsg);
+/**
+ * GTestLogFatalFunc:
+ * @log_domain: the log domain of the message
+ * @log_level: the log level of the message (including the fatal and recursion flags)
+ * @message: the message to process
+ * @user_data: user data, set in g_test_log_set_fatal_handler()
+ *
+ * Specifies the prototype of fatal log handler functions.
+ *
+ * Return value: %TRUE if the program should abort, %FALSE otherwise
+ *
+ * Since: 2.22
+ */
+typedef gboolean (*GTestLogFatalFunc) (const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer user_data);
+void
+g_test_log_set_fatal_handler (GTestLogFatalFunc log_func,
+ gpointer user_data);
+
G_END_DECLS
#endif /* __G_TEST_UTILS_H__ */
diff --git a/glib/tests/testing.c b/glib/tests/testing.c
index cfbf8d4d2..ef8bcf98d 100644
--- a/glib/tests/testing.c
+++ b/glib/tests/testing.c
@@ -191,6 +191,32 @@ test_random_conversions (void)
g_free (str);
}
+static gboolean
+fatal_handler (const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer user_data)
+{
+ return FALSE;
+}
+
+static void
+test_log_handler (void)
+{
+ g_test_log_set_fatal_handler (fatal_handler, NULL);
+ g_str_has_prefix (NULL, "file://");
+ g_critical ("Test passing");
+
+ g_test_log_set_fatal_handler (NULL, NULL);
+ if (g_test_trap_fork (0, 0))
+ g_error ("Test failing");
+ g_test_trap_assert_failed ();
+
+ if (g_test_trap_fork (0, 0))
+ g_str_has_prefix (NULL, "file://");
+ g_test_trap_assert_failed ();
+}
+
int
main (int argc,
char *argv[])
@@ -209,6 +235,7 @@ main (int argc,
g_test_add_func ("/forking/patterns", test_fork_patterns);
if (g_test_slow())
g_test_add_func ("/forking/timeout", test_fork_timeout);
+ g_test_add_func ("/misc/log-handler", test_log_handler);
return g_test_run();
}