check: Add a function to check destruction of objects
authorThibault Saunier <tsaunier@gnome.org>
Thu, 11 Sep 2014 13:52:32 +0000 (15:52 +0200)
committerThibault Saunier <tsaunier@gnome.org>
Fri, 12 Sep 2014 15:18:21 +0000 (17:18 +0200)
Add a method letting people to ensure that unreffing one object
leads to its destruction, and possibly the destruction of more object
(think destruction of a GstBin etc...).

https://bugzilla.gnome.org/show_bug.cgi?id=736477

docs/libs/gstreamer-libs-sections.txt
libs/gst/check/Makefile.am
libs/gst/check/gstcheck.c
libs/gst/check/gstcheck.h

index a27b372..1b52239 100644 (file)
@@ -985,6 +985,8 @@ gst_check_setup_sink_pad_by_name_from_template
 gst_check_setup_sink_pad_from_template
 gst_check_setup_src_pad_by_name_from_template
 gst_check_setup_src_pad_from_template
+gst_check_objects_destroyed_on_unref
+gst_check_object_destroyed_on_unref
 
 <SUBSECTION Private>
 MAIN_INIT
index 1389270..4adf53c 100644 (file)
@@ -93,6 +93,8 @@ LIBGSTCHECK_EXPORTED_FUNCS = \
        gst_check_teardown_pad_by_name \
        gst_check_teardown_sink_pad \
        gst_check_teardown_src_pad \
+       gst_check_objects_destroyed_on_unref \
+       gst_check_object_destroyed_on_unref \
        gst_consistency_checker_add_pad \
        gst_consistency_checker_new \
        gst_consistency_checker_reset \
index 7f1ba9c..fcb428a 100644 (file)
@@ -927,3 +927,87 @@ gst_check_setup_events (GstPad * srcpad, GstElement * element,
       stream_id);
   g_free (stream_id);
 }
+
+typedef struct _DestroyedObjectStruct
+{
+  GObject *object;
+  gboolean destroyed;
+} DestroyedObjectStruct;
+
+static void
+weak_notify (DestroyedObjectStruct * destroyed, GObject ** object)
+{
+  destroyed->destroyed = TRUE;
+}
+
+/**
+ * gst_check_objects_destroyed_on_unref:
+ * @object_to_unref: The #GObject to unref
+ * @first_object: (allow-none) The first object that should be destroyed as a
+ * concequence of unrefing @object_to_unref.
+ * @... : Additional object that should have been destroyed.
+ *
+ * Unrefs @object_to_unref and checks that is has properly been
+ * destroyed, also checks that the other objects passed in
+ * parametter have been destroyed as a concequence of
+ * unrefing @object_to_unref. Last variable argument should be NULL.
+ *
+ * Since: 1.6
+ */
+void
+gst_check_objects_destroyed_on_unref (gpointer object_to_unref, gpointer first_object, ...)
+{
+  GObject *object;
+  GList *objs = NULL, *tmp;
+  DestroyedObjectStruct *destroyed = g_slice_new0 (DestroyedObjectStruct);
+
+  destroyed->object = object_to_unref;
+  g_object_weak_ref (object_to_unref, (GWeakNotify) weak_notify, destroyed);
+  objs = g_list_prepend (objs, destroyed);
+
+  if (first_object) {
+    va_list varargs;
+
+    object = first_object;
+
+    va_start (varargs, first_object);
+    while (object) {
+      destroyed = g_slice_new0 (DestroyedObjectStruct);
+      destroyed->object = object;
+      g_object_weak_ref (object, (GWeakNotify) weak_notify, destroyed);
+      objs = g_list_prepend (objs, destroyed);
+      object = va_arg (varargs, GObject *);
+    }
+    va_end (varargs);
+  }
+  gst_object_unref (object_to_unref);
+
+  for (tmp = objs; tmp; tmp = tmp->next) {
+    DestroyedObjectStruct *destroyed = tmp->data;
+
+    if (destroyed->destroyed == FALSE) {
+      fail_unless (destroyed->destroyed == TRUE,
+          "%s_%p is not destroyed, %d refcounts left!",
+          GST_IS_OBJECT (destroyed->object) ? GST_OBJECT_NAME (destroyed->object) :
+          G_OBJECT_TYPE_NAME (destroyed),
+          destroyed->object, destroyed->object->ref_count);
+    }
+    g_slice_free (DestroyedObjectStruct, tmp->data);
+  }
+  g_list_free (objs);
+}
+
+/**
+ * gst_check_object_destroyed_on_unref:
+ * @object_to_unref: The #GObject to unref
+ *
+ * Unrefs @object_to_unref and checks that is has properly been
+ * destroyed.
+ *
+ * Since: 1.6
+ */
+void
+gst_check_object_destroyed_on_unref (gpointer object_to_unref)
+{
+  gst_check_objects_destroyed_on_unref (object_to_unref, NULL, NULL);
+}
index 84d1d11..e33e006 100644 (file)
@@ -107,6 +107,9 @@ void gst_check_setup_events (GstPad * srcpad, GstElement * element,
 void gst_check_setup_events_with_stream_id (GstPad * srcpad,
     GstElement * element, GstCaps * caps, GstFormat format,
     const gchar * stream_id);
+void gst_check_objects_destroyed_on_unref (gpointer object_to_unref, gpointer first_object, ...)
+  G_GNUC_NULL_TERMINATED;
+void gst_check_object_destroyed_on_unref (gpointer object_to_unref);
 
 #define fail_unless_message_error(msg, domain, code)            \
 gst_check_message_error (msg, GST_MESSAGE_ERROR,                \