[Telepathy-commits] [telepathy-glib/master] Check TpChannel's group signals fire exactly once per change.
Will Thompson
will.thompson at collabora.co.uk
Mon Jan 5 11:51:12 PST 2009
If the group channel has the Members_Changed_Detailed flag, then
TpChannel should only listen to the new signal; if not, it should only
listen to the former. Regardless, both GObject signals should fire
exactly once per change.
---
tests/dbus/cli-group.c | 236 ++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 200 insertions(+), 36 deletions(-)
diff --git a/tests/dbus/cli-group.c b/tests/dbus/cli-group.c
index 1022c68..ec4cbcf 100644
--- a/tests/dbus/cli-group.c
+++ b/tests/dbus/cli-group.c
@@ -16,6 +16,7 @@
#include <telepathy-glib/gtypes.h>
#include <telepathy-glib/proxy-subclass.h>
+#include "tests/lib/debug.h"
#include "tests/lib/myassert.h"
#include "tests/lib/simple-conn.h"
#include "tests/lib/textchan-group.h"
@@ -23,9 +24,14 @@
static int fail = 0;
static GMainLoop *mainloop;
-TestTextChannelGroup *service_chan_1, *service_chan_2;
+SimpleConnection *service_conn;
+gchar *conn_path;
+TpConnection *conn;
TpHandleRepoIface *contact_repo;
-TpHandle self_handle;
+TpHandle self_handle, h1, h2, h3;
+
+gboolean expecting_group_members_changed = FALSE;
+gboolean expecting_group_members_changed_detailed = FALSE;
static void
myassert_failed (void)
@@ -33,18 +39,201 @@ myassert_failed (void)
fail = 1;
}
+static void
+group_members_changed_cb (TpChannel *chan_,
+ gchar *message,
+ GArray *added,
+ GArray *removed,
+ GArray *local_pending,
+ GArray *remote_pending,
+ guint actor,
+ guint reason,
+ gpointer user_data)
+{
+ DEBUG ("\"%s\", %u, %u, %u, %u, %u, %u", message, added->len, removed->len,
+ local_pending->len, remote_pending->len, actor, reason);
+ MYASSERT (expecting_group_members_changed, "");
+
+ expecting_group_members_changed = FALSE;
+}
+
+static void
+group_members_changed_detailed_cb (TpChannel *chan_,
+ GArray *added,
+ GArray *removed,
+ GArray *local_pending,
+ GArray *remote_pending,
+ GHashTable *details,
+ gpointer user_data)
+{
+ DEBUG ("%u, %u, %u, %u, %u details", added->len, removed->len,
+ local_pending->len, remote_pending->len, g_hash_table_size (details));
+ MYASSERT (expecting_group_members_changed_detailed, "");
+
+ expecting_group_members_changed_detailed = FALSE;
+}
+
+
+static void
+test_channel_proxy (TestTextChannelGroup *service_chan,
+ TpChannel *chan,
+ gboolean detailed)
+{
+ TpIntSet *add, *rem, *expected_members;
+ GArray *arr, *yarr;
+ GError *error = NULL;
+ TpChannelGroupFlags flags;
+ gboolean has_detailed_flag;
+
+ MYASSERT (tp_channel_run_until_ready (chan, &error, NULL), "");
+ MYASSERT_NO_ERROR (error);
+
+ /* We want to ensure that each of these signals fires exactly once per
+ * change. The channel emits both MembersChanged and MembersChangedDetailed,
+ * but TpChannel should only be reacting to one of them, based on whether the
+ * Members_Changed_Detailed flag is set. So, each signal's handler has a
+ * corresponding "expected" flag, which it asserts on then sets back to FALSE.
+ */
+ g_signal_connect (chan, "group-members-changed",
+ (GCallback) group_members_changed_cb, NULL);
+ g_signal_connect (chan, "group-members-changed-detailed",
+ (GCallback) group_members_changed_detailed_cb, NULL);
+
+ flags = tp_channel_group_get_flags (chan);
+ has_detailed_flag = !!(flags & TP_CHANNEL_GROUP_FLAG_MEMBERS_CHANGED_DETAILED);
+ MYASSERT (detailed == has_detailed_flag,
+ ": expected Members_Changed_Detailed to be %sset",
+ (detailed ? "" : "un"));
+
+ /* Add a couple of members. */
+ add = tp_intset_new ();
+ tp_intset_add (add, h1);
+ tp_intset_add (add, h2);
+
+ expecting_group_members_changed = TRUE;
+ expecting_group_members_changed_detailed = TRUE;
+ tp_group_mixin_change_members ((GObject *) service_chan,
+ "quantum tunnelling", add, NULL, NULL, NULL, 0,
+ TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
+
+ /* Clear the queue to ensure that there aren't any more
+ * MembersChanged[Detailed] signals waiting for us.
+ */
+ test_connection_run_until_dbus_queue_processed (conn);
+
+ expected_members = add;
+ MYASSERT (tp_intset_is_equal (expected_members,
+ tp_channel_group_get_members (chan)), "");
+
+ /* Add one, remove one. Check that the cache is properly updated. */
+ add = tp_intset_new ();
+ tp_intset_add (add, h3);
+ rem = tp_intset_new ();
+ tp_intset_add (rem, h1);
+
+ expecting_group_members_changed = TRUE;
+ expecting_group_members_changed_detailed = TRUE;
+ tp_group_mixin_change_members ((GObject *) service_chan,
+ "goat", add, rem, NULL, NULL, 0,
+ TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
+ tp_intset_destroy (add);
+ tp_intset_destroy (rem);
+
+ test_connection_run_until_dbus_queue_processed (conn);
+
+ tp_intset_add (expected_members, h3);
+ tp_intset_remove (expected_members, h1);
+
+ MYASSERT (tp_intset_is_equal (expected_members,
+ tp_channel_group_get_members (chan)), "");
+
+ /* Now, emit a spurious instance of whichever DBus signal the proxy should
+ * not be listening to to check it's really not listening to it. If the
+ * TpChannel is reacting to the wrong DBus signal, it'll trigger an assertion
+ * in the GObject signal handlers.
+ */
+ yarr = g_array_new (FALSE, FALSE, sizeof (TpHandle));
+ arr = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 1);
+ g_array_insert_val (arr, 0, h1);
+
+ expecting_group_members_changed = FALSE;
+ expecting_group_members_changed_detailed = FALSE;
+
+ if (detailed)
+ {
+ tp_svc_channel_interface_group_emit_members_changed (service_chan,
+ "whee", arr, yarr, yarr, yarr, 0,
+ TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
+ }
+ else
+ {
+ GHashTable *details = g_hash_table_new (NULL, NULL);
+
+ tp_svc_channel_interface_group_emit_members_changed_detailed (
+ service_chan, arr, yarr, yarr, yarr, details);
+ g_hash_table_unref (details);
+ }
+
+ g_array_free (yarr, TRUE);
+ g_array_free (arr, TRUE);
+
+ test_connection_run_until_dbus_queue_processed (conn);
+
+ /* And, the cache of group members should be unaltered, since the signal the
+ * TpChannel cares about was not fired.
+ */
+ MYASSERT (tp_intset_is_equal (expected_members,
+ tp_channel_group_get_members (chan)), "");
+
+ tp_intset_destroy (expected_members);
+}
+
+static void
+run_test (guint channel_number,
+ gboolean detailed)
+{
+ gchar *chan_path;
+ TestTextChannelGroup *service_chan;
+ TpChannel *chan;
+ GError *error = NULL;
+
+ chan_path = g_strdup_printf ("%s/Channel%u", conn_path, channel_number);
+ service_chan = TEST_TEXT_CHANNEL_GROUP (g_object_new (
+ TEST_TYPE_TEXT_CHANNEL_GROUP,
+ "connection", service_conn,
+ "object-path", chan_path,
+ "detailed", detailed,
+ NULL));
+ chan = tp_channel_new (conn, chan_path, NULL, TP_UNKNOWN_HANDLE_TYPE, 0,
+ &error);
+
+ MYASSERT_NO_ERROR (error);
+
+ test_channel_proxy (service_chan, chan, detailed);
+
+ g_object_unref (chan);
+ g_object_unref (service_chan);
+ g_free (chan_path);
+}
+
+static void
+run_tests (void)
+{
+ /* Run a set of sanity checks on two channels, one of which has the
+ * Members_Changed_Details flag cleared and one of which has it set.
+ */
+ run_test (1, FALSE);
+ run_test (2, TRUE);
+}
+
int
main (int argc,
char **argv)
{
- SimpleConnection *service_conn;
TpBaseConnection *service_conn_as_base;
TpDBusDaemon *dbus;
- TpConnection *conn;
GError *error = NULL;
gchar *name;
- gchar *conn_path;
- gchar *chan_path_1, *chan_path_2;
g_type_init ();
tp_debug_set_flags ("all");
@@ -73,38 +262,17 @@ main (int argc,
contact_repo = tp_base_connection_get_handles (service_conn_as_base,
TP_HANDLE_TYPE_CONTACT);
MYASSERT (contact_repo != NULL, "");
- self_handle = tp_handle_ensure (contact_repo, "me at example.com", NULL, NULL);
-
- chan_path_1 = g_strdup_printf ("%s/Channel1", conn_path);
- service_chan_1 = TEST_TEXT_CHANNEL_GROUP (g_object_new (
- TEST_TYPE_TEXT_CHANNEL_GROUP,
- "connection", service_conn,
- "object-path", chan_path_1,
- "detailed", FALSE,
- NULL));
-
- chan_path_2 = g_strdup_printf ("%s/Channel2", conn_path);
- service_chan_2 = TEST_TEXT_CHANNEL_GROUP (g_object_new (
- TEST_TYPE_TEXT_CHANNEL_GROUP,
- "connection", service_conn,
- "object-path", chan_path_2,
- "detailed", TRUE,
- NULL));
+ self_handle = tp_handle_ensure (contact_repo, "me at example.com", NULL, NULL);
+ h1 = tp_handle_ensure (contact_repo, "h1", NULL, NULL);
+ h2 = tp_handle_ensure (contact_repo, "h2", NULL, NULL);
+ h3 = tp_handle_ensure (contact_repo, "h3", NULL, NULL);
mainloop = g_main_loop_new (NULL, FALSE);
MYASSERT (tp_cli_connection_run_connect (conn, -1, &error, NULL), "");
MYASSERT_NO_ERROR (error);
- /* Tests go here.
- *
- * - check that group-members-changed and group-members-changed-detailed
- * both fire once per change on a channel without the Detailed flag.
- * - ditto for a channel with the detailed flag.
- * - in both cases, check that the client-side cache matches reality.
- * - if feeling very keen, emit spurious MembersChanged signals on a channel
- * without Detailed set (and vice versa), and check they're ignored.
- */
+ run_tests ();
MYASSERT (tp_cli_connection_run_disconnect (conn, -1, &error, NULL), "");
MYASSERT_NO_ERROR (error);
@@ -115,16 +283,12 @@ main (int argc,
mainloop = NULL;
g_object_unref (conn);
- g_object_unref (service_chan_2);
- g_object_unref (service_chan_1);
service_conn_as_base = NULL;
g_object_unref (service_conn);
g_object_unref (dbus);
g_free (name);
g_free (conn_path);
- g_free (chan_path_1);
- g_free (chan_path_2);
return fail;
}
--
1.5.6.5
More information about the Telepathy-commits
mailing list