summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2014-04-08 18:03:16 -0400
committerXavier Claessens <xavier.claessens@collabora.com>2014-04-10 12:35:40 -0400
commit4b19019e6d615b7f3ae6b89f30acabeb1203e252 (patch)
treea07270b68012b1ca398b0b79f40e63708d411eb5
parent1cc470d15d26bf99ad8ec2ba306226b11846fd31 (diff)
test-self-handle: Fix possible race making test sometimes fail
The filter callback is ran in GDBusConnection's worker thread so we can't be sure how stuff are ordered. By delaying the GetAll reply and re-send it from the main thread we are sure that the SelfContactChanged signal will be sent just after it.
-rw-r--r--tests/dbus/self-handle.c92
1 files changed, 62 insertions, 30 deletions
diff --git a/tests/dbus/self-handle.c b/tests/dbus/self-handle.c
index 464cd7423..6d0683c58 100644
--- a/tests/dbus/self-handle.c
+++ b/tests/dbus/self-handle.c
@@ -32,6 +32,9 @@ typedef struct {
TpConnection *client_conn;
TpHandleRepoIface *contact_repo;
GAsyncResult *result;
+
+ guint get_all_serial;
+ GDBusMessage *message;
} Fixture;
static void
@@ -97,21 +100,6 @@ swapped_counter_cb (gpointer user_data)
++*times;
}
-static GDBusMessage *
-got_all_counter_filter (GDBusConnection *connection,
- GDBusMessage *message,
- gboolean incoming,
- gpointer user_data)
-{
- guint *times = user_data;
-
- if (incoming &&
- !tp_strdiff (g_dbus_message_get_member (message), "GetAll"))
- ++*times;
-
- return message;
-}
-
static void
test_self_handle (Fixture *f,
gconstpointer unused G_GNUC_UNUSED)
@@ -218,12 +206,69 @@ test_change_early (Fixture *f,
g_object_unref (after);
}
+static gboolean
+change_self_contact_after_get_all_idle_cb (gpointer user_data)
+{
+ Fixture *f = user_data;
+ GError *error = NULL;
+
+ f->get_all_serial = 0;
+
+ /* We can now resend the GetAll reply, closely followed by a self contact
+ * change. */
+ g_dbus_connection_send_message (f->dbus, f->message,
+ G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_object (&f->message);
+
+ DEBUG ("changing my own identifier to something else");
+ tp_tests_simple_connection_set_identifier (f->service_conn,
+ "myself@example.org");
+ g_assert_cmpstr (tp_handle_inspect (f->contact_repo,
+ tp_base_connection_get_self_handle (f->service_conn_as_base)), ==,
+ "myself@example.org");
+
+ return G_SOURCE_REMOVE;
+}
+
+static GDBusMessage *
+change_self_contact_after_get_all_filter (GDBusConnection *connection,
+ GDBusMessage *message,
+ gboolean incoming,
+ gpointer user_data)
+{
+ Fixture *f = user_data;
+
+ if (!incoming)
+ return message;
+
+ if (!tp_strdiff (g_dbus_message_get_member (message), "GetAll") &&
+ !tp_strdiff (g_dbus_message_get_path (message),
+ tp_proxy_get_object_path (f->client_conn)))
+ {
+ /* We just received TpConnection's GetAll message, remember the serial
+ * to catch the reply message later. */
+ f->get_all_serial = g_dbus_message_get_serial (message);
+ }
+ else if (f->get_all_serial != 0 &&
+ g_dbus_message_get_reply_serial (message) == f->get_all_serial)
+ {
+ /* This is the reply, delay that message until an idle callback to avoid
+ * threading issues. */
+ f->message = message;
+ message = NULL;
+ g_idle_add (change_self_contact_after_get_all_idle_cb, f);
+ }
+
+ return message;
+}
+
static void
test_change_inconveniently (Fixture *f,
gconstpointer arg)
{
TpContact *after;
- guint contact_times = 0, got_all_times = 0;
+ guint contact_times = 0;
gboolean ok;
GQuark features[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 };
guint filter_id;
@@ -238,8 +283,7 @@ test_change_inconveniently (Fixture *f,
g_signal_connect_swapped (f->client_conn, "notify::self-contact",
G_CALLBACK (swapped_counter_cb), &contact_times);
filter_id = g_dbus_connection_add_filter (f->dbus,
- got_all_counter_filter,
- &got_all_times, NULL);
+ change_self_contact_after_get_all_filter, f, NULL);
tp_proxy_prepare_async (f->client_conn, features, tp_tests_result_ready_cb,
&f->result);
@@ -258,18 +302,6 @@ test_change_inconveniently (Fixture *f,
TP_CONNECTION_STATUS_CONNECTED,
TP_CONNECTION_STATUS_REASON_REQUESTED);
- /* run the main loop until just after GetAll(Connection)
- * is processed, to make sure the client first saw the old self handle */
- while (got_all_times == 0)
- g_main_context_iteration (NULL, TRUE);
-
- DEBUG ("changing my own identifier to something else");
- tp_tests_simple_connection_set_identifier (f->service_conn,
- "myself@example.org");
- g_assert_cmpstr (tp_handle_inspect (f->contact_repo,
- tp_base_connection_get_self_handle (f->service_conn_as_base)), ==,
- "myself@example.org");
-
/* now run the main loop and let the client catch up */
tp_tests_run_until_result (&f->result);
ok = tp_proxy_prepare_finish (f->client_conn, f->result, &f->error);