[next] telepathy-glib: tp_tests_await_last_unref: add

Simon McVittie smcv at kemper.freedesktop.org
Tue Mar 18 05:45:05 PDT 2014


Module: telepathy-glib
Branch: next
Commit: 64f58b0b6c3da84b154c33488627205c58524176
URL:    http://cgit.freedesktop.org/telepathy/telepathy-glib/commit/?id=64f58b0b6c3da84b154c33488627205c58524176

Author: Simon McVittie <simon.mcvittie at collabora.co.uk>
Date:   Mon Mar 17 15:04:19 2014 +0000

tp_tests_await_last_unref: add

---

 tests/lib/util.c |   59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/lib/util.h |   15 ++++++++++++++
 2 files changed, 74 insertions(+)

diff --git a/tests/lib/util.c b/tests/lib/util.c
index a09199b..3efd3fb 100644
--- a/tests/lib/util.c
+++ b/tests/lib/util.c
@@ -27,6 +27,8 @@
 #include <gio/gunixconnection.h>
 #endif
 
+#include "debug.h"
+
 void
 tp_tests_proxy_run_until_prepared (gpointer proxy,
     const GQuark *features)
@@ -779,3 +781,60 @@ _tp_tests_assert_last_unref (gpointer obj,
     g_error ("%s:%d: %s %p should not have had any more references",
         file, line, G_OBJECT_TYPE_NAME (obj), obj);
 }
+
+/*
+ * tp_tests_await_last_unref:
+ * @op: a pointer to a #GObject
+ *
+ * Set @op to point to %NULL, release one reference to the object to which
+ * it previously pointed, and wait for that object to be freed by iterating
+ * the default (NULL) main-context.
+ *
+ * For instance, suppose you have this code, and you want to adapt it to
+ * assert that @obj is not leaked:
+ *
+ * |[
+ * obj = my_object_new ();
+ * my_object_do_thing_async (obj, NULL, NULL);
+ * g_clear_object (&obj);
+ * ]|
+ *
+ * Because #GAsyncResult async calls take a ref to the
+ * source object for the duration of the async call, this will cause
+ * an assertion failure:
+ *
+ * |[
+ * obj = my_object_new ();
+ * my_object_do_thing_async (obj, NULL, NULL);
+ * tp_tests_assert_last_unref (&obj);
+ * ]|
+ *
+ * but this is OK, and will wait for the `do_thing_async` call to finish:
+ *
+ * |[
+ * obj = my_object_new ();
+ * my_object_do_thing_async (obj, NULL, NULL);
+ * tp_tests_await_last_unref (&obj);
+ * ]|
+ */
+/* Really a macro, this is its implementation. @obj is the original `*op` */
+void
+_tp_tests_await_last_unref (gpointer obj,
+    const gchar *file,
+    int line)
+{
+  GWeakRef weak;
+
+  g_weak_ref_init (&weak, obj);
+  g_object_unref (obj);
+  obj = g_weak_ref_get (&weak);
+
+  while (obj != NULL)
+    {
+      DEBUG ("%s %p still has references, waiting...",
+          G_OBJECT_TYPE_NAME (obj), obj);
+      g_object_unref (obj);
+      g_main_context_iteration (NULL, TRUE);
+      obj = g_weak_ref_get (&weak);
+    }
+}
diff --git a/tests/lib/util.h b/tests/lib/util.h
index b82ead8..fbfb8f8 100644
--- a/tests/lib/util.h
+++ b/tests/lib/util.h
@@ -108,6 +108,21 @@ TpChannel *tp_tests_channel_new_from_properties (TpConnection *conn,
 
 GHashTable * tp_tests_dup_channel_props_asv (TpChannel *channel);
 
+#define tp_tests_await_last_unref(op) \
+  G_STMT_START \
+    { \
+      gpointer _tmp; \
+      \
+      _tmp = *(op); \
+      *(op) = NULL; \
+      \
+      _tp_tests_await_last_unref (_tmp, __FILE__, __LINE__); \
+    } \
+  G_STMT_END
+void _tp_tests_await_last_unref (gpointer obj,
+    const gchar *file,
+    int line);
+
 #define tp_tests_assert_last_unref(op) \
   G_STMT_START \
     { \



More information about the telepathy-commits mailing list