+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),
{
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]);
(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,
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)
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);
};
/* --- 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;
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);
}
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,
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();
}
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 };
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))
{