capture g_log() messages and send to gtester. also, send assertion
author20:30:18 Tim Janik <timj@imendio.com>
Wed, 19 Dec 2007 19:28:55 +0000 (19:28 +0000)
committerTim Janik <timj@src.gnome.org>
Wed, 19 Dec 2007 19:28:55 +0000 (19:28 +0000)
2007-12-19 20:30:18  Tim Janik  <timj@imendio.com>

        * glib/gtestutils.c: capture g_log() messages and send to gtester.
        also, send assertion messages to gtester.

        * glib/gtester.c: add error messages to output log file.
        force child poll loop to abort if waitpid() signaled child exit,
        eventhough the child's report file descriptor wasn't closed.

svn path=/trunk/; revision=6163

ChangeLog
glib/gtester.c
glib/gtestutils.c

index d1437630a8665d3515281ae1da001515213e463e..349f11c7d517b3c65c2738ca80699bb68b0a858b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2007-12-19 20:30:18  Tim Janik  <timj@imendio.com>
+
+        * glib/gtestutils.c: capture g_log() messages and send to gtester.
+       also, send assertion messages to gtester.
+
+       * glib/gtester.c: add error messages to output log file.
+       force child poll loop to abort if waitpid() signaled child exit,
+       eventhough the child's report file descriptor wasn't closed.
+
 2007-12-19  Christian Persch  <chpe@gnome.org>
 
        * glib/gchecksum.c: (g_checksum_type_get_length),
index 62337b7244267c11f181bf01a3a107646771e5cc..ac91ef19916e89909c73d50362effab88c648bb4 100644 (file)
@@ -122,10 +122,15 @@ test_log_msg (GTestLogMsg *msg)
 {
   switch (msg->log_type)
     {
+      guint i;
+      gchar **strv;
     case G_TEST_LOG_NONE:
       break;
     case G_TEST_LOG_ERROR:
-      g_printerr ("%s\n", msg->strings[0]);
+      strv = g_strsplit (msg->strings[0], "\n", -1);
+      for (i = 0; strv[i]; i++)
+        test_log_printfe ("%s<error>%s</error>\n", sindent (log_indent), strv[i]);
+      g_strfreev (strv);
       break;
     case G_TEST_LOG_START_BINARY:
       test_log_printfe ("%s<binary file=\"%s\"/>\n", sindent (log_indent), msg->strings[0]);
@@ -219,6 +224,7 @@ child_report_cb (GIOChannel  *source,
       (void) status;
     }
   while (length > 0);
+  // g_print ("LASTIOSTATE: first_read_eof=%d condition=%d\n", first_read_eof, condition);
   if (first_read_eof || (condition & (G_IO_ERR | G_IO_HUP)))
     {
       /* if there's no data to read and select() reports an error or hangup,
@@ -270,6 +276,8 @@ launch_test_binary (const char *binary,
   const gchar *argv[99 + g_slist_length (subtest_args) + g_slist_length (subtest_paths)];
   GPid pid = 0;
   gint report_pipe[2] = { -1, -1 };
+  guint child_report_cb_id = 0;
+  gboolean loop_pending;
   gint i = 0;
 
   if (pipe (report_pipe) < 0)
@@ -347,16 +355,27 @@ launch_test_binary (const char *binary,
       g_io_channel_set_flags (ioc_report, G_IO_FLAG_NONBLOCK, NULL);
       g_io_channel_set_encoding (ioc_report, NULL, NULL);
       g_io_channel_set_buffered (ioc_report, FALSE);
-      g_io_add_watch_full (ioc_report, G_PRIORITY_DEFAULT - 1, G_IO_IN | G_IO_ERR | G_IO_HUP, child_report_cb, tlb, NULL);
+      child_report_cb_id = g_io_add_watch_full (ioc_report, G_PRIORITY_DEFAULT - 1, G_IO_IN | G_IO_ERR | G_IO_HUP, child_report_cb, tlb, NULL);
       g_io_channel_unref (ioc_report);
     }
   g_child_watch_add_full (G_PRIORITY_DEFAULT + 1, pid, child_watch_cb, NULL, NULL);
 
-  while (subtest_running ||             /* FALSE once child exits */
-         subtest_io_pending ||          /* FALSE once ioc_report closes */
-         g_main_context_pending (NULL)) /* TRUE while idler, etc are running */
-    g_main_context_iteration (NULL, TRUE);
+  loop_pending = g_main_context_pending (NULL);
+  while (subtest_running ||     /* FALSE once child exits */
+         subtest_io_pending ||  /* FALSE once ioc_report closes */
+         loop_pending)          /* TRUE while idler, etc are running */
+    {
+      // g_print ("LOOPSTATE: subtest_running=%d subtest_io_pending=%d\n", subtest_running, subtest_io_pending);
+      /* check for unexpected hangs that are not signalled on report_pipe */
+      if (!subtest_running &&   /* child exited */
+          subtest_io_pending && /* no EOF detected on report_pipe */
+          !loop_pending)        /* no IO events pending however */
+        break;
+      g_main_context_iteration (NULL, TRUE);
+      loop_pending = g_main_context_pending (NULL);
+    }
 
+  g_source_remove (child_report_cb_id);
   close (report_pipe[0]);
   g_test_log_buffer_free (tlb);
 
index c182cbc3dcb17018fb0a89e09efab6b021d1bdcf..af9695bd74ee0b50f969396629577e928ba13106 100644 (file)
@@ -64,10 +64,15 @@ struct DestroyEntry
 };
 
 /* --- prototypes --- */
-static void                     test_run_seed           (const gchar *rseed);
-static void                     test_trap_clear         (void);
-static guint8*                  g_test_log_dump         (GTestLogMsg *msg,
-                                                         guint       *len);
+static void     test_run_seed                   (const gchar *rseed);
+static void     test_trap_clear                 (void);
+static guint8*  g_test_log_dump                 (GTestLogMsg *msg,
+                                                 guint       *len);
+static void     gtest_default_log_handler       (const gchar    *log_domain,
+                                                 GLogLevelFlags  log_level,
+                                                 const gchar    *message,
+                                                 gpointer        unused_data);
+
 
 /* --- variables --- */
 static int         test_log_fd = -1;
@@ -430,6 +435,7 @@ g_test_init (int    *argc,
   test_run_seed (test_run_seedstr);
 
   /* report program start */
+  g_log_set_default_handler (gtest_default_log_handler, NULL);
   g_test_log (G_TEST_LOG_START_BINARY, g_get_prgname(), test_run_seedstr, 0, NULL);
 }
 
@@ -1097,6 +1103,45 @@ g_test_run_suite (GTestSuite *suite)
   return n_bad;
 }
 
+static void
+gtest_default_log_handler (const gchar    *log_domain,
+                           GLogLevelFlags  log_level,
+                           const gchar    *message,
+                           gpointer        unused_data)
+{
+  const gchar *strv[16];
+  gchar *msg;
+  guint i = 0;
+  if (log_domain)
+    {
+      strv[i++] = log_domain;
+      strv[i++] = "-";
+    }
+  if (log_level & G_LOG_FLAG_FATAL)
+    strv[i++] = "FATAL-";
+  if (log_level & G_LOG_FLAG_RECURSION)
+    strv[i++] = "RECURSIVE-";
+  if (log_level & G_LOG_LEVEL_ERROR)
+    strv[i++] = "ERROR";
+  if (log_level & G_LOG_LEVEL_CRITICAL)
+    strv[i++] = "CRITICAL";
+  if (log_level & G_LOG_LEVEL_WARNING)
+    strv[i++] = "WARNING";
+  if (log_level & G_LOG_LEVEL_MESSAGE)
+    strv[i++] = "MESSAGE";
+  if (log_level & G_LOG_LEVEL_INFO)
+    strv[i++] = "INFO";
+  if (log_level & G_LOG_LEVEL_DEBUG)
+    strv[i++] = "DEBUG";
+  strv[i++] = ": ";
+  strv[i++] = message;
+  strv[i++] = NULL;
+  msg = g_strjoinv ("", (gchar**) strv);
+  g_test_log (G_TEST_LOG_ERROR, msg, NULL, 0, NULL);
+  g_log_default_handler (log_domain, log_level, message, unused_data);
+  g_free (msg);
+}
+
 void
 g_assertion_message (const char     *domain,
                      const char     *file,
@@ -1114,6 +1159,7 @@ g_assertion_message (const char     *domain,
                    func, func[0] ? ":" : "",
                    " ", message, NULL);
   g_printerr ("**\n** %s\n", s);
+  g_test_log (G_TEST_LOG_ERROR, s, NULL, 0, NULL);
   g_free (s);
   abort();
 }
@@ -1363,6 +1409,7 @@ g_test_trap_fork (guint64        usec_timeout,
                   GTestTrapFlags test_trap_flags)
 {
 #ifdef G_OS_UNIX
+  gboolean pass_on_forked_log = FALSE;
   int stdout_pipe[2] = { -1, -1 };
   int stderr_pipe[2] = { -1, -1 };
   int stdtst_pipe[2] = { -1, -1 };
@@ -1441,7 +1488,7 @@ g_test_trap_fork (guint64        usec_timeout,
               gint l, r = read (stdtst_pipe[0], buffer, sizeof (buffer));
               if (r > 0 && test_log_fd > 0)
                 do
-                  l = write (test_log_fd, buffer, r);
+                  l = write (pass_on_forked_log ? test_log_fd : -1, buffer, r);
                 while (l < 0 && errno == EINTR);
               if (r == 0 || (r < 0 && errno != EINTR && errno != EAGAIN))
                 {