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.
This commit is contained in:
Christian Dywan 2009-09-10 16:40:11 +02:00 committed by Christian Dywan
parent 4b1217b7e0
commit 278ac0a45d
5 changed files with 97 additions and 2 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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__ */

View File

@ -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();
}