[glib: 9/17] tests: Add timeout to assert_connection_has_one_ref()



commit ac274b400577131d7f52320d14077410b607b76e
Author: Philip Withnall <withnall endlessm com>
Date:   Fri Feb 21 12:18:29 2020 +0000

    tests: Add timeout to assert_connection_has_one_ref()
    
    Iterate the given `context` while waiting, rather than sleeping. This
    ensures that if the errant `GDBusConnection` ref is held by some pending
    callback in the given `context`, it will actually be released.
    
    Typically `context` is going to be the global default main context.
    
    Signed-off-by: Philip Withnall <withnall endlessm com>
    
    Helps: #1515

 gio/tests/gdbus-threading.c | 50 +++++++++++++++++++++++++++++++++------------
 1 file changed, 37 insertions(+), 13 deletions(-)
---
diff --git a/gio/tests/gdbus-threading.c b/gio/tests/gdbus-threading.c
index b2112b07b..b57888a78 100644
--- a/gio/tests/gdbus-threading.c
+++ b/gio/tests/gdbus-threading.c
@@ -27,26 +27,50 @@
 /* all tests rely on a global connection */
 static GDBusConnection *c = NULL;
 
+typedef struct
+{
+  GMainContext *context;
+  gboolean timed_out;
+} TimeoutData;
+
+static gboolean
+timeout_cb (gpointer user_data)
+{
+  TimeoutData *data = user_data;
+
+  data->timed_out = TRUE;
+  g_main_context_wakeup (data->context);
+
+  return G_SOURCE_REMOVE;
+}
+
 /* Check that the given @connection has only one ref, waiting to let any pending
  * unrefs complete first. This is typically used on the shared connection, to
  * ensure it’s in a correct state before beginning the next test. */
 static void
-assert_connection_has_one_ref (GDBusConnection *connection)
+assert_connection_has_one_ref (GDBusConnection *connection,
+                               GMainContext    *context)
 {
-  guint j;
+  GSource *timeout_source = NULL;
+  TimeoutData data = { context, FALSE };
 
-  for (j = 0; j < 1000; j++)
-    {
-      guint r = g_atomic_int_get (&G_OBJECT (connection)->ref_count);
+  if (g_atomic_int_get (&G_OBJECT (connection)->ref_count) == 1)
+    return;
 
-      if (r == 1)
-        break;
+  timeout_source = g_timeout_source_new_seconds (1);
+  g_source_set_callback (timeout_source, timeout_cb, &data, NULL);
+  g_source_attach (timeout_source, context);
 
-      g_debug ("refcount of %p is %u, sleeping", connection, r);
-      g_usleep (1000);
+  while (g_atomic_int_get (&G_OBJECT (connection)->ref_count) != 1 && !data.timed_out)
+    {
+      g_debug ("refcount of %p is not right, sleeping", connection);
+      g_main_context_iteration (NULL, TRUE);
     }
 
-  if (j == 1000)
+  g_source_destroy (timeout_source);
+  g_source_unref (timeout_source);
+
+  if (g_atomic_int_get (&G_OBJECT (connection)->ref_count) != 1)
     g_error ("connection %p had too many refs", connection);
 }
 
@@ -253,7 +277,7 @@ test_delivery_in_thread (void)
 
   g_thread_join (thread);
 
-  assert_connection_has_one_ref (c);
+  assert_connection_has_one_ref (c, NULL);
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -467,7 +491,7 @@ test_method_calls_in_thread (void)
   if (g_test_verbose ())
     g_printerr ("\n");
 
-  assert_connection_has_one_ref (c);
+  assert_connection_has_one_ref (c, NULL);
 }
 
 #define SLEEP_MIN_USEC 1
@@ -536,7 +560,7 @@ test_threaded_singleton (void)
       GDBusConnection *new_conn;
 
       /* We want to be the last ref, so let it finish setting up */
-      assert_connection_has_one_ref (c);
+      assert_connection_has_one_ref (c, NULL);
 
       if (g_test_verbose () && (i % (n/50)) == 0)
         g_printerr ("%u%%\n", ((i * 100) / n));


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]