mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 11:11:08 +00:00
check: Add API to filter g_warning/g_critical etc
New API functions to filter log messages before they are processed by GstCheck. This can be used to discard specific messages that are accepted by the test or to add callbacks that test specific messages. Default bevavior when no callback is given to a filter is to discard the message, because it does not makes sense to have a filter with no callback which does not discard; that would be a noop. Discarded messages will in addition to bypass the GstCheck handling also return to GLib that the message is not fatal if it occurs. https://bugzilla.gnome.org/show_bug.cgi?id=773091
This commit is contained in:
parent
a533b6c2f9
commit
0c36e5766d
3 changed files with 234 additions and 2 deletions
|
@ -74,6 +74,9 @@ LIBGSTCHECK_EXPORTED_FUNCS = \
|
|||
gst_check_element_push_buffer \
|
||||
gst_check_element_push_buffer_list \
|
||||
gst_check_init \
|
||||
gst_check_add_log_filter \
|
||||
gst_check_remove_log_filter \
|
||||
gst_check_clear_log_filter \
|
||||
gst_check_message_error \
|
||||
gst_check_run_suite \
|
||||
gst_check_setup_element \
|
||||
|
|
|
@ -61,11 +61,204 @@ gboolean _gst_check_raised_critical = FALSE;
|
|||
gboolean _gst_check_raised_warning = FALSE;
|
||||
gboolean _gst_check_expecting_log = FALSE;
|
||||
gboolean _gst_check_list_tests = FALSE;
|
||||
static GQueue _gst_check_log_filters = G_QUEUE_INIT;
|
||||
static GMutex _gst_check_log_filters_mutex;
|
||||
|
||||
struct _GstCheckLogFilter {
|
||||
gchar *log_domain;
|
||||
GLogLevelFlags log_level;
|
||||
GRegex *regex;
|
||||
GstCheckLogFilterFunc func;
|
||||
gpointer user_data;
|
||||
GDestroyNotify destroy;
|
||||
};
|
||||
|
||||
|
||||
static gboolean
|
||||
gst_check_match_log_filter (const GstCheckLogFilter * filter,
|
||||
const gchar * log_domain, GLogLevelFlags log_level, const gchar * message)
|
||||
{
|
||||
if (g_strcmp0 (log_domain, filter->log_domain) != 0)
|
||||
return FALSE;
|
||||
|
||||
if ((log_level & filter->log_level) == 0)
|
||||
return FALSE;
|
||||
|
||||
if (!g_regex_match (filter->regex, message, 0, NULL))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstCheckLogFilter *
|
||||
gst_check_alloc_log_filter (const gchar * log_domain, GLogLevelFlags log_level,
|
||||
GRegex * regex, GstCheckLogFilterFunc func, gpointer user_data,
|
||||
GDestroyNotify destroy_data)
|
||||
{
|
||||
GstCheckLogFilter *filter;
|
||||
|
||||
filter = g_slice_new (GstCheckLogFilter);
|
||||
filter->log_domain = g_strdup (log_domain);
|
||||
filter->log_level = log_level;
|
||||
filter->regex = regex;
|
||||
filter->func = func;
|
||||
filter->user_data = user_data;
|
||||
filter->destroy = destroy_data;
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_check_free_log_filter (GstCheckLogFilter * filter)
|
||||
{
|
||||
if (!filter)
|
||||
return;
|
||||
|
||||
g_free (filter->log_domain);
|
||||
g_regex_unref (filter->regex);
|
||||
if (filter->destroy)
|
||||
filter->destroy (filter->user_data);
|
||||
g_slice_free (GstCheckLogFilter, filter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_check_add_log_filter:
|
||||
* @log_domain: the log domain of the message
|
||||
* @log_level: the log level of the message
|
||||
* @regex: (transfer full): a #GRegex to match the message
|
||||
* @func: the function to call for matching messages
|
||||
* @user_data: the user data to pass to @func
|
||||
* @destroy_data: #GDestroyNotify for @user_data
|
||||
*
|
||||
* Add a callback @func to be called for all log messages that matches
|
||||
* @log_domain, @log_level and @regex. If @func is NULL the
|
||||
* matching logs will be silently discarded by GstCheck.
|
||||
*
|
||||
* MT safe.
|
||||
*
|
||||
* Returns: A filter that can be passed to @gst_check_remove_log_filter.
|
||||
*
|
||||
* Since: 1.12
|
||||
**/
|
||||
GstCheckLogFilter *
|
||||
gst_check_add_log_filter (const gchar * log_domain, GLogLevelFlags log_level,
|
||||
GRegex * regex, GstCheckLogFilterFunc func, gpointer user_data,
|
||||
GDestroyNotify destroy_data)
|
||||
{
|
||||
GstCheckLogFilter *filter;
|
||||
|
||||
g_return_val_if_fail (regex != NULL, NULL);
|
||||
|
||||
filter = gst_check_alloc_log_filter (log_domain, log_level, regex,
|
||||
func, user_data, destroy_data);
|
||||
g_mutex_lock (&_gst_check_log_filters_mutex);
|
||||
g_queue_push_tail (&_gst_check_log_filters, filter);
|
||||
g_mutex_unlock (&_gst_check_log_filters_mutex);
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_check_remove_log_filter:
|
||||
* @filter: Filter returned by @gst_check_add_log_filter
|
||||
*
|
||||
* Remove a filter that has been added by @gst_check_add_log_filter.
|
||||
*
|
||||
* MT safe.
|
||||
*
|
||||
* Since: 1.12
|
||||
**/
|
||||
void
|
||||
gst_check_remove_log_filter (GstCheckLogFilter * filter)
|
||||
{
|
||||
g_mutex_lock (&_gst_check_log_filters_mutex);
|
||||
g_queue_remove (&_gst_check_log_filters, filter);
|
||||
gst_check_free_log_filter (filter);
|
||||
g_mutex_unlock (&_gst_check_log_filters_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_check_clear_log_filter:
|
||||
*
|
||||
* Clear all filters added by @gst_check_add_log_filter.
|
||||
*
|
||||
* MT safe.
|
||||
*
|
||||
* Since: 1.12
|
||||
**/
|
||||
void
|
||||
gst_check_clear_log_filter (void)
|
||||
{
|
||||
g_mutex_lock (&_gst_check_log_filters_mutex);
|
||||
g_queue_foreach (&_gst_check_log_filters,
|
||||
(GFunc) gst_check_free_log_filter, NULL);
|
||||
g_queue_clear (&_gst_check_log_filters);
|
||||
g_mutex_unlock (&_gst_check_log_filters_mutex);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const gchar * domain;
|
||||
const gchar * message;
|
||||
GLogLevelFlags level;
|
||||
gboolean discard;
|
||||
} LogFilterApplyData;
|
||||
|
||||
static void
|
||||
gst_check_apply_log_filter (GstCheckLogFilter * filter,
|
||||
LogFilterApplyData * data)
|
||||
{
|
||||
if (gst_check_match_log_filter (filter, data->domain, data->level,
|
||||
data->message)) {
|
||||
if (filter->func)
|
||||
data->discard |= filter->func (data->domain, data->level,
|
||||
data->message, filter->user_data);
|
||||
else
|
||||
data->discard = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_check_filter_log_filter (const gchar * log_domain,
|
||||
GLogLevelFlags log_level, const gchar * message)
|
||||
{
|
||||
LogFilterApplyData data;
|
||||
|
||||
data.domain = log_domain;
|
||||
data.level = log_level;
|
||||
data.message = message;
|
||||
data.discard = FALSE;
|
||||
|
||||
g_mutex_lock (&_gst_check_log_filters_mutex);
|
||||
g_queue_foreach (&_gst_check_log_filters, (GFunc) gst_check_apply_log_filter,
|
||||
&data);
|
||||
g_mutex_unlock (&_gst_check_log_filters_mutex);
|
||||
|
||||
if (data.discard)
|
||||
GST_DEBUG ("Discarding message: %s", message);
|
||||
|
||||
return data.discard;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_check_log_fatal_func (const gchar * log_domain, GLogLevelFlags log_level,
|
||||
const gchar *message, gpointer user_data)
|
||||
{
|
||||
if (gst_check_filter_log_filter (log_domain, log_level, message))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void gst_check_log_message_func
|
||||
(const gchar * log_domain, GLogLevelFlags log_level,
|
||||
const gchar * message, gpointer user_data)
|
||||
{
|
||||
if (gst_check_filter_log_filter (log_domain, log_level, message))
|
||||
return;
|
||||
|
||||
if (_gst_check_debug) {
|
||||
g_print ("%s\n", message);
|
||||
}
|
||||
|
@ -75,6 +268,9 @@ static void gst_check_log_critical_func
|
|||
(const gchar * log_domain, GLogLevelFlags log_level,
|
||||
const gchar * message, gpointer user_data)
|
||||
{
|
||||
if (gst_check_filter_log_filter (log_domain, log_level, message))
|
||||
return;
|
||||
|
||||
if (!_gst_check_expecting_log) {
|
||||
g_print ("\n\nUnexpected critical/warning: %s\n", message);
|
||||
fail ("Unexpected critical/warning: %s", message);
|
||||
|
@ -119,6 +315,13 @@ print_plugins (void)
|
|||
gst_plugin_list_free (plugins);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_check_deinit (void)
|
||||
{
|
||||
gst_deinit ();
|
||||
gst_check_clear_log_filter ();
|
||||
}
|
||||
|
||||
/* gst_check_init:
|
||||
* @argc: (inout) (allow-none): pointer to application's argc
|
||||
* @argv: (inout) (array length=argc) (allow-none): pointer to application's argv
|
||||
|
@ -155,8 +358,8 @@ gst_check_init (int *argc, char **argv[])
|
|||
|
||||
GST_DEBUG_CATEGORY_INIT (check_debug, "check", 0, "check regression tests");
|
||||
|
||||
if (atexit (gst_deinit) != 0) {
|
||||
GST_ERROR ("failed to set gst_deinit as exit function");
|
||||
if (atexit (gst_check_deinit) != 0) {
|
||||
GST_ERROR ("failed to set gst_check_deinit as exit function");
|
||||
}
|
||||
|
||||
if (g_getenv ("GST_TEST_DEBUG"))
|
||||
|
@ -174,6 +377,7 @@ gst_check_init (int *argc, char **argv[])
|
|||
gst_check_log_critical_func, NULL);
|
||||
g_log_set_handler ("GLib", G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING,
|
||||
gst_check_log_critical_func, NULL);
|
||||
g_test_log_set_fatal_handler (gst_check_log_fatal_func, NULL);
|
||||
|
||||
print_plugins ();
|
||||
|
||||
|
|
|
@ -63,8 +63,33 @@ typedef struct
|
|||
}
|
||||
GstCheckABIStruct;
|
||||
|
||||
typedef struct _GstCheckLogFilter GstCheckLogFilter;
|
||||
|
||||
/**
|
||||
* GstCheckLogFilterFunc:
|
||||
* @log_domain: the log domain of the message
|
||||
* @log_level: the log level of the message
|
||||
* @message: the message that has occured
|
||||
* @user_data: user data
|
||||
*
|
||||
* A function that is called for messages matching the filter added by
|
||||
* @gst_check_add_log_filter.
|
||||
*
|
||||
* Returns: %TRUE if message should be discarded by GstCheck.
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
typedef gboolean (*GstCheckLogFilterFunc) (const gchar * log_domain,
|
||||
GLogLevelFlags log_level, const gchar * message, gpointer user_data);
|
||||
|
||||
void gst_check_init (int *argc, char **argv[]);
|
||||
|
||||
GstCheckLogFilter * gst_check_add_log_filter (const gchar * log,
|
||||
GLogLevelFlags log_level, GRegex * regex, GstCheckLogFilterFunc func,
|
||||
gpointer user_data, GDestroyNotify destroy_data);
|
||||
void gst_check_remove_log_filter (GstCheckLogFilter * filter);
|
||||
void gst_check_clear_log_filter (void);
|
||||
|
||||
GstFlowReturn gst_check_chain_func (GstPad * pad, GstObject * parent, GstBuffer * buffer);
|
||||
|
||||
void gst_check_message_error (GstMessage * message, GstMessageType type,
|
||||
|
|
Loading…
Reference in a new issue