[glib] Bug 579050 Allow making selected critical and warning messages non-fatal



commit 278ac0a45d2b677a0928b1c31b3e20a4c265ffb0
Author: Christian Dywan <christian lanedo com>
Date:   Thu Sep 10 16:40:11 2009 +0200

    Bug 579050 Allow making selected critical and warning messages non-fatal
    
    Implement g_test_log_set_fatal_handler which is a function similar to
    g_log_set_default_handler but for use in unit tests where certain
    errors have to be ignored because it is not possible to fix or avoid
    them otherwise. A unit test is added.

 glib/glib.symbols    |    3 +++
 glib/gmessages.c     |   47 +++++++++++++++++++++++++++++++++++++++++++++--
 glib/gtestutils.c    |    1 +
 glib/gtestutils.h    |   21 +++++++++++++++++++++
 glib/tests/testing.c |   27 +++++++++++++++++++++++++++
 5 files changed, 97 insertions(+), 2 deletions(-)
---
diff --git a/glib/glib.symbols b/glib/glib.symbols
index 0a96980..6e3a63b 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 e080ad6..0f4bf42 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 3f19fbc..fdb9494 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 4c47458..ac1ed28 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 cfbf8d4..ef8bcf9 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();
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]