diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2010-05-21 16:31:09 +0100 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2010-05-21 16:31:09 +0100 |
commit | c403d57a5ebebd9fbaa0b136f56257076adfafb9 (patch) | |
tree | e91c6dec464d7c3637bd8dc75b4e57ae72e527e7 | |
parent | df5238a9ec5427d0931579f60be70161c5408aae (diff) | |
parent | fa5ca18312eed17ab2b4f5e3238e64463fe29beb (diff) |
Merge branch 'test-contact-list-cm'
-rw-r--r-- | examples/cm/contactlist/conn.c | 18 | ||||
-rw-r--r-- | examples/cm/contactlist/connection-manager.c | 2 | ||||
-rw-r--r-- | examples/cm/contactlist/contact-list-manager.c | 87 | ||||
-rw-r--r-- | examples/cm/contactlist/manager-file.py | 4 | ||||
-rw-r--r-- | tests/dbus/Makefile.am | 6 | ||||
-rw-r--r-- | tests/dbus/contact-lists.c | 936 | ||||
-rw-r--r-- | tests/lib/util.c | 37 | ||||
-rw-r--r-- | tests/lib/util.h | 6 |
8 files changed, 1088 insertions, 8 deletions
diff --git a/examples/cm/contactlist/conn.c b/examples/cm/contactlist/conn.c index 89588e7e..b335702f 100644 --- a/examples/cm/contactlist/conn.c +++ b/examples/cm/contactlist/conn.c @@ -38,12 +38,14 @@ G_DEFINE_TYPE_WITH_CODE (ExampleContactListConnection, enum { PROP_ACCOUNT = 1, + PROP_SIMULATION_DELAY, N_PROPS }; struct _ExampleContactListConnectionPrivate { gchar *account; + guint simulation_delay; ExampleContactListManager *list_manager; gboolean away; }; @@ -71,6 +73,10 @@ get_property (GObject *object, g_value_set_string (value, self->priv->account); break; + case PROP_SIMULATION_DELAY: + g_value_set_uint (value, self->priv->simulation_delay); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); } @@ -92,6 +98,10 @@ set_property (GObject *object, self->priv->account = g_value_dup_string (value); break; + case PROP_SIMULATION_DELAY: + self->priv->simulation_delay = g_value_get_uint (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); } @@ -221,6 +231,7 @@ create_channel_managers (TpBaseConnection *conn) EXAMPLE_CONTACT_LIST_MANAGER (g_object_new ( EXAMPLE_TYPE_CONTACT_LIST_MANAGER, "connection", conn, + "simulation-delay", self->priv->simulation_delay, NULL)); g_signal_connect (self->priv->list_manager, "alias-updated", @@ -431,6 +442,13 @@ example_contact_list_connection_class_init ( G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_ACCOUNT, param_spec); + param_spec = g_param_spec_uint ("simulation-delay", "Simulation delay", + "Delay between simulated network events", + 0, G_MAXUINT32, 1000, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_SIMULATION_DELAY, + param_spec); + tp_contacts_mixin_class_init (object_class, G_STRUCT_OFFSET (ExampleContactListConnectionClass, contacts_mixin)); tp_presence_mixin_class_init (object_class, diff --git a/examples/cm/contactlist/connection-manager.c b/examples/cm/contactlist/connection-manager.c index 9c75629e..dda422a0 100644 --- a/examples/cm/contactlist/connection-manager.c +++ b/examples/cm/contactlist/connection-manager.c @@ -38,6 +38,7 @@ example_contact_list_connection_manager_init ( typedef struct { gchar *account; + guint simulation_delay; } ExampleParams; static gboolean @@ -93,6 +94,7 @@ new_connection (TpBaseConnectionManager *self, conn = EXAMPLE_CONTACT_LIST_CONNECTION (g_object_new (EXAMPLE_TYPE_CONTACT_LIST_CONNECTION, "account", params->account, + "simulation-delay", params->simulation_delay, "protocol", proto, NULL)); diff --git a/examples/cm/contactlist/contact-list-manager.c b/examples/cm/contactlist/contact-list-manager.c index 279f26be..160637ff 100644 --- a/examples/cm/contactlist/contact-list-manager.c +++ b/examples/cm/contactlist/contact-list-manager.c @@ -101,12 +101,14 @@ static guint signals[N_SIGNALS] = { 0 }; enum { PROP_CONNECTION = 1, + PROP_SIMULATION_DELAY, N_PROPS }; struct _ExampleContactListManagerPrivate { TpBaseConnection *conn; + guint simulation_delay; TpHandleRepoIface *contact_repo; TpHandleRepoIface *group_repo; @@ -252,6 +254,11 @@ get_property (GObject *object, case PROP_CONNECTION: g_value_set_object (value, self->priv->conn); break; + + case PROP_SIMULATION_DELAY: + g_value_set_uint (value, self->priv->simulation_delay); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -273,6 +280,11 @@ set_property (GObject *object, * less than its lifetime */ self->priv->conn = g_value_get_object (value); break; + + case PROP_SIMULATION_DELAY: + self->priv->simulation_delay = g_value_get_uint (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -318,6 +330,13 @@ ensure_contact (ExampleContactListManager *self, g_hash_table_insert (self->priv->contact_details, GUINT_TO_POINTER (contact), ret); + + if (created != NULL) + *created = TRUE; + } + else if (created != NULL) + { + *created = FALSE; } return ret; @@ -507,7 +526,7 @@ receive_contact_lists (gpointer p) NULL, NULL, NULL, set, 0, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_group_mixin_change_members ((GObject *) stored, "", - NULL, NULL, NULL, set, + set, NULL, NULL, NULL, 0, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_intset_fast_iter_init (&iter, set); @@ -536,6 +555,9 @@ receive_contact_lists (gpointer p) "I'm more metal than you!", NULL, NULL, set, NULL, handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); + tp_group_mixin_change_members ((GObject *) stored, "", + set, NULL, NULL, NULL, + handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_intset_destroy (set); g_signal_emit (self, signals[ALIAS_UPDATED], 0, handle); g_signal_emit (self, signals[PRESENCE_UPDATED], 0, handle); @@ -553,6 +575,9 @@ receive_contact_lists (gpointer p) "I have some fermented herring for you", NULL, NULL, set, NULL, handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); + tp_group_mixin_change_members ((GObject *) stored, "", + set, NULL, NULL, NULL, + handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_intset_destroy (set); g_signal_emit (self, signals[ALIAS_UPDATED], 0, handle); g_signal_emit (self, signals[PRESENCE_UPDATED], 0, handle); @@ -600,7 +625,8 @@ status_changed_cb (TpBaseConnection *conn, /* Do network I/O to get the contact list. This connection manager * doesn't really have a server, so simulate a small network delay * then invent a contact list */ - g_timeout_add_full (G_PRIORITY_DEFAULT, 1000, receive_contact_lists, + g_timeout_add_full (G_PRIORITY_DEFAULT, + 2 * self->priv->simulation_delay, receive_contact_lists, g_object_ref (self), g_object_unref); } break; @@ -653,6 +679,13 @@ example_contact_list_manager_class_init (ExampleContactListManagerClass *klass) G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); + param_spec = g_param_spec_uint ("simulation-delay", "Simulation delay", + "Delay between simulated network events", + 0, G_MAXUINT32, 1000, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_SIMULATION_DELAY, + param_spec); + g_type_class_add_private (klass, sizeof (ExampleContactListManagerPrivate)); signals[ALIAS_UPDATED] = g_signal_new ("alias-updated", @@ -1115,6 +1148,8 @@ receive_auth_request (ExampleContactListManager *self, TpIntSet *set; ExampleContactList *publish = self->priv->lists[ EXAMPLE_CONTACT_LIST_PUBLISH]; + ExampleContactList *stored = self->priv->lists[ + EXAMPLE_CONTACT_LIST_STORED]; /* if shutting down, do nothing */ if (publish == NULL) @@ -1140,6 +1175,9 @@ receive_auth_request (ExampleContactListManager *self, "May I see your presence, please?", NULL, NULL, set, NULL, contact, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); + tp_group_mixin_change_members ((GObject *) stored, "", + set, NULL, NULL, NULL, + contact, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_intset_destroy (set); } @@ -1151,6 +1189,8 @@ receive_authorized (gpointer p) TpIntSet *set; ExampleContactList *subscribe = s->self->priv->lists[ EXAMPLE_CONTACT_LIST_SUBSCRIBE]; + ExampleContactList *stored = s->self->priv->lists[ + EXAMPLE_CONTACT_LIST_STORED]; /* A remote contact has accepted our request to see their presence. * @@ -1173,6 +1213,9 @@ receive_authorized (gpointer p) tp_group_mixin_change_members ((GObject *) subscribe, "", set, NULL, NULL, NULL, s->contact, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); + tp_group_mixin_change_members ((GObject *) stored, "", + set, NULL, NULL, NULL, + s->contact, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_intset_destroy (set); /* their presence changes to something other than UNKNOWN */ @@ -1238,6 +1281,7 @@ example_contact_list_manager_add_to_list (ExampleContactListManager *self, GError **error) { TpIntSet *set; + ExampleContactList *stored = self->priv->lists[EXAMPLE_CONTACT_LIST_STORED]; switch (list) { @@ -1268,9 +1312,14 @@ example_contact_list_manager_add_to_list (ExampleContactListManager *self, NULL, NULL, NULL, set, self->priv->conn->self_handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); + /* subscribing to someone implicitly puts them on Stored, too */ + tp_group_mixin_change_members ((GObject *) stored, "", + set, NULL, NULL, NULL, + self->priv->conn->self_handle, + TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_intset_destroy (set); - /* Pretend that after 500ms, the contact notices the request + /* Pretend that after a delay, the contact notices the request * and allows or rejects it. In this example connection manager, * empty requests are allowed, as are requests that contain "please" * case-insensitively. All other requests are denied. */ @@ -1278,13 +1327,15 @@ example_contact_list_manager_add_to_list (ExampleContactListManager *self, if (message[0] == '\0' || strstr (message_lc, "please") != NULL) { - g_timeout_add_full (G_PRIORITY_DEFAULT, 500, receive_authorized, + g_timeout_add_full (G_PRIORITY_DEFAULT, + self->priv->simulation_delay, receive_authorized, self_and_contact_new (self, member), self_and_contact_destroy); } else { - g_timeout_add_full (G_PRIORITY_DEFAULT, 500, + g_timeout_add_full (G_PRIORITY_DEFAULT, + self->priv->simulation_delay, receive_unauthorized, self_and_contact_new (self, member), self_and_contact_destroy); @@ -1302,6 +1353,8 @@ example_contact_list_manager_add_to_list (ExampleContactListManager *self, if (d == NULL || !d->publish_requested) { + /* the group mixin won't actually allow this to be reached, + * because of the flags we set */ g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE, "Can't unilaterally send presence to %s", tp_handle_inspect (self->priv->contact_repo, member)); @@ -1319,6 +1372,10 @@ example_contact_list_manager_add_to_list (ExampleContactListManager *self, set, NULL, NULL, NULL, self->priv->conn->self_handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); + tp_group_mixin_change_members ((GObject *) stored, "", + set, NULL, NULL, NULL, + self->priv->conn->self_handle, + TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_intset_destroy (set); } } @@ -1403,9 +1460,10 @@ example_contact_list_manager_remove_from_list (ExampleContactListManager *self, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_intset_destroy (set); - /* Pretend that after 500ms, the contact notices the change + /* Pretend that after a delay, the contact notices the change * and asks for our presence again */ - g_timeout_add_full (G_PRIORITY_DEFAULT, 500, auth_request_cb, + g_timeout_add_full (G_PRIORITY_DEFAULT, + self->priv->simulation_delay, auth_request_cb, self_and_contact_new (self, member), self_and_contact_destroy); } @@ -1474,7 +1532,9 @@ example_contact_list_manager_remove_from_list (ExampleContactListManager *self, case EXAMPLE_CONTACT_LIST_STORED: /* we would like to remove member from the roster altogether */ { - if (lookup_contact (self, member) != NULL) + ExampleContactDetails *d = lookup_contact (self, member); + + if (d != NULL) { g_hash_table_remove (self->priv->contact_details, GUINT_TO_POINTER (member)); @@ -1485,6 +1545,16 @@ example_contact_list_manager_remove_from_list (ExampleContactListManager *self, NULL, set, NULL, NULL, self->priv->conn->self_handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); + tp_group_mixin_change_members ( + (GObject *) self->priv->lists[EXAMPLE_CONTACT_LIST_SUBSCRIBE], + "", NULL, set, NULL, NULL, + self->priv->conn->self_handle, + TP_CHANNEL_GROUP_CHANGE_REASON_NONE); + tp_group_mixin_change_members ( + (GObject *) self->priv->lists[EXAMPLE_CONTACT_LIST_PUBLISH], + "", NULL, set, NULL, NULL, + self->priv->conn->self_handle, + TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_intset_destroy (set); tp_handle_set_remove (self->priv->contacts, member); @@ -1493,6 +1563,7 @@ example_contact_list_manager_remove_from_list (ExampleContactListManager *self, * see their presence, so emit a signal changing it to * UNKNOWN */ g_signal_emit (self, signals[PRESENCE_UPDATED], 0, member); + } } return TRUE; diff --git a/examples/cm/contactlist/manager-file.py b/examples/cm/contactlist/manager-file.py index 2e668a81..499de629 100644 --- a/examples/cm/contactlist/manager-file.py +++ b/examples/cm/contactlist/manager-file.py @@ -12,6 +12,10 @@ PARAMS = { # 'struct_field': '...', # 'setter_data': 'NULL', }, + 'simulation-delay': { + 'dtype': 'u', + 'default': 1000, + }, }, } STRUCTS = { diff --git a/tests/dbus/Makefile.am b/tests/dbus/Makefile.am index 8f040ab5..30c2ae55 100644 --- a/tests/dbus/Makefile.am +++ b/tests/dbus/Makefile.am @@ -18,6 +18,7 @@ noinst_PROGRAMS = \ test-connection-handles \ test-connection-inject-bug16307 \ test-connection-getinterfaces-failure \ + test-contact-lists \ test-contacts \ test-contacts-bug-19101 \ test-contacts-mixin \ @@ -89,6 +90,11 @@ test_cm_LDADD = \ test_connection_SOURCES = connection.c +test_contact_lists_SOURCES = contact-lists.c +test_contact_lists_LDADD = \ + $(LDADD) \ + $(top_builddir)/examples/cm/contactlist/libexample-cm-contactlist.la + test_connection_bug_18845_SOURCES = connection-bug-18845.c test_connection_handles_SOURCES = connection-handles.c diff --git a/tests/dbus/contact-lists.c b/tests/dbus/contact-lists.c new file mode 100644 index 00000000..d75b6ac4 --- /dev/null +++ b/tests/dbus/contact-lists.c @@ -0,0 +1,936 @@ +/* Feature test for contact lists + * + * Copyright © 2007-2010 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright © 2007-2008 Nokia Corporation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include <telepathy-glib/connection.h> + +#include "examples/cm/contactlist/conn.h" +#include "tests/lib/util.h" + +typedef struct { + TpDBusDaemon *dbus; + ExampleContactListConnection *service_conn; + TpBaseConnection *service_conn_as_base; + gchar *conn_name; + gchar *conn_path; + TpConnection *conn; + + TpChannel *publish; + TpChannel *subscribe; + TpChannel *stored; + + TpChannel *group; + + TpHandleRepoIface *contact_repo; + TpHandle sjoerd; + TpHandle helen; + TpHandle wim; + TpHandle ninja; + + GArray *arr; + + GAsyncResult *prepare_result; +} Test; + +static void +setup (Test *test, + gconstpointer data) +{ + GError *error = NULL; + GQuark features[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 }; + + g_type_init (); + tp_debug_set_flags ("all"); + test->dbus = test_dbus_daemon_dup_or_die (); + + test->service_conn = test_object_new_static_class ( + EXAMPLE_TYPE_CONTACT_LIST_CONNECTION, + "account", "me@example.com", + "simulation-delay", 0, + "protocol", "example-contact-list", + NULL); + test->service_conn_as_base = TP_BASE_CONNECTION (test->service_conn); + g_assert (test->service_conn != NULL); + g_assert (test->service_conn_as_base != NULL); + + g_assert (tp_base_connection_register (test->service_conn_as_base, "example", + &test->conn_name, &test->conn_path, &error)); + g_assert_no_error (error); + + test->contact_repo = tp_base_connection_get_handles ( + test->service_conn_as_base, TP_HANDLE_TYPE_CONTACT); + + test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path, + &error); + g_assert (test->conn != NULL); + g_assert_no_error (error); + tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL); + test_proxy_run_until_prepared (test->conn, features); + + g_assert (tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE)); + g_assert (tp_proxy_is_prepared (test->conn, + TP_CONNECTION_FEATURE_CONNECTED)); + + test->sjoerd = tp_handle_ensure (test->contact_repo, "sjoerd@example.com", + NULL, NULL); + g_assert (test->sjoerd != 0); + test->helen = tp_handle_ensure (test->contact_repo, "helen@example.com", + NULL, NULL); + g_assert (test->helen != 0); + test->wim = tp_handle_ensure (test->contact_repo, "wim@example.com", + NULL, NULL); + g_assert (test->wim != 0); + test->ninja = tp_handle_ensure (test->contact_repo, "ninja@example.com", + NULL, NULL); + g_assert (test->ninja != 0); + + test->arr = g_array_new (FALSE, FALSE, sizeof (TpHandle)); +} + +static void +teardown (Test *test, + gconstpointer data) +{ + TpConnection *conn; + gboolean ok; + GError *error = NULL; + + g_array_free (test->arr, TRUE); + + tp_handle_unref (test->contact_repo, test->sjoerd); + tp_handle_unref (test->contact_repo, test->helen); + tp_handle_unref (test->contact_repo, test->wim); + tp_handle_unref (test->contact_repo, test->ninja); + + test_clear_object (&test->conn); + test_clear_object (&test->publish); + test_clear_object (&test->subscribe); + test_clear_object (&test->stored); + test_clear_object (&test->group); + + /* make a new TpConnection just to disconnect the underlying Connection, + * so we don't leak it */ + conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path, + &error); + g_assert (conn != NULL); + g_assert_no_error (error); + ok = tp_cli_connection_run_disconnect (conn, -1, &error, NULL); + g_assert (ok); + g_assert_no_error (error); + g_assert (!tp_connection_run_until_ready (conn, FALSE, &error, NULL)); + g_assert_error (error, TP_ERRORS, TP_ERROR_CANCELLED); + g_clear_error (&error); + + test->service_conn_as_base = NULL; + g_object_unref (test->service_conn); + g_free (test->conn_name); + g_free (test->conn_path); + + g_object_unref (test->dbus); + test->dbus = NULL; +} + +static TpChannel * +test_ensure_channel (Test *test, + guint channel_type, + const gchar *id) +{ + GError *error = NULL; + GHashTable *asv, *props; + gchar *path; + TpChannel *ret; + + asv = tp_asv_new ( + TP_PROP_CHANNEL_CHANNEL_TYPE, + G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_CONTACT_LIST, + TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, + G_TYPE_UINT, channel_type, + TP_PROP_CHANNEL_TARGET_ID, + G_TYPE_STRING, id, + NULL); + tp_cli_connection_interface_requests_run_ensure_channel (test->conn, -1, + asv, NULL, &path, &props, &error, NULL); + g_assert_no_error (error); + ret = tp_channel_new_from_properties (test->conn, path, props, + &error); + g_assert (ret != NULL); + g_assert_no_error (error); + g_free (path); + g_hash_table_unref (props); + g_hash_table_unref (asv); + + test_proxy_run_until_prepared (ret, NULL); + return ret; +} + +static void +test_nothing (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + /* this is actually a valuable test - it ensures that shutting down the + * CM before the contact list has been retrieved works! */ +} + +static void +test_initial_channels (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish"); + test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, + "subscribe"); + test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->publish)), ==, 4); + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_local_pending (test->publish)), + ==, 2); + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_remote_pending (test->publish)), + ==, 0); + g_assert (tp_intset_is_member (tp_channel_group_get_members (test->publish), + test->sjoerd)); + g_assert (tp_intset_is_member ( + tp_channel_group_get_local_pending (test->publish), + test->wim)); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->subscribe)), ==, 4); + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_local_pending (test->subscribe)), + ==, 0); + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_remote_pending (test->subscribe)), + ==, 2); + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->subscribe), + test->sjoerd)); + g_assert (tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->subscribe), + test->helen)); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->stored)), ==, 8); + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_local_pending (test->stored)), + ==, 0); + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_remote_pending (test->stored)), + ==, 0); + g_assert (tp_intset_is_member (tp_channel_group_get_members (test->stored), + test->sjoerd)); + + g_assert (!tp_intset_is_member (tp_channel_group_get_members (test->publish), + test->ninja)); + g_assert (!tp_intset_is_member (tp_channel_group_get_members ( + test->subscribe), + test->ninja)); + g_assert (!tp_intset_is_member (tp_channel_group_get_members (test->stored), + test->ninja)); +} + +static void +test_accept_publish_request (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_local_pending (test->publish)), + ==, 2); + g_assert (tp_intset_is_member ( + tp_channel_group_get_local_pending (test->publish), + test->wim)); + + g_array_append_val (test->arr, test->wim); + tp_cli_channel_interface_group_run_add_members (test->publish, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); + + /* by the time the method returns, we should have had the + * change-notification, too */ + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_local_pending (test->publish)), + ==, 1); + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->wim)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_local_pending (test->publish), + test->wim)); +} + +static void +test_reject_publish_request (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish"); + + g_assert (tp_intset_is_member ( + tp_channel_group_get_local_pending (test->publish), + test->wim)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->wim)); + + g_array_append_val (test->arr, test->wim); + tp_cli_channel_interface_group_run_remove_members (test->publish, + -1, test->arr, "", &error, NULL); + + /* by the time the method returns, we should have had the + * removal-notification, too */ + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_local_pending (test->publish)), + ==, 1); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->wim)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_local_pending (test->publish), + test->wim)); +} + +static void +test_add_to_publish_invalid (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + /* Unilaterally adding a member to the publish channel doesn't work. */ + + test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish"); + + g_assert (!tp_intset_is_member ( + tp_channel_group_get_local_pending (test->publish), + test->ninja)); + + g_array_append_val (test->arr, test->ninja); + tp_cli_channel_interface_group_run_add_members (test->publish, + -1, test->arr, "", &error, NULL); + g_assert_error (error, TP_ERRORS, TP_ERROR_PERMISSION_DENIED); + g_clear_error (&error); + + g_assert (!tp_intset_is_member ( + tp_channel_group_get_local_pending (test->publish), + test->ninja)); +} + +static void +test_add_to_publish_no_op (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + /* Adding a member to the publish channel when they're already there is + * valid. */ + + test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish"); + + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->sjoerd)); + + g_array_append_val (test->arr, test->sjoerd); + tp_cli_channel_interface_group_run_add_members (test->publish, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); + + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->sjoerd)); +} + +static void +test_remove_from_publish (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->publish)), + ==, 4); + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->sjoerd)); + + g_array_append_val (test->arr, test->sjoerd); + tp_cli_channel_interface_group_run_remove_members (test->publish, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); + + /* by the time the method returns, we should have had the + * removal-notification, too */ + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->sjoerd)); + + /* the contact re-requests our presence after a short delay */ + while (!tp_intset_is_member ( + tp_channel_group_get_local_pending (test->publish), + test->sjoerd)) + g_main_context_iteration (NULL, TRUE); + + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->sjoerd)); + g_assert (tp_intset_is_member ( + tp_channel_group_get_local_pending (test->publish), + test->sjoerd)); +} + +static void +test_remove_from_publish_no_op (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->publish)), + ==, 4); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->ninja)); + + g_array_append_val (test->arr, test->ninja); + tp_cli_channel_interface_group_run_remove_members (test->publish, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); +} + +static void +test_add_to_stored (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored"); + test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish"); + test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, + "subscribe"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->stored)), + ==, 8); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->stored), + test->ninja)); + + g_array_append_val (test->arr, test->ninja); + tp_cli_channel_interface_group_run_add_members (test->stored, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); + + /* by the time the method returns, we should have had the + * change-notification, too */ + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->stored)), + ==, 9); + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->stored), + test->ninja)); + + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->subscribe), + test->ninja)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->ninja)); +} + +static void +test_add_to_stored_no_op (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->stored)), + ==, 8); + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->stored), + test->sjoerd)); + + g_array_append_val (test->arr, test->sjoerd); + tp_cli_channel_interface_group_run_add_members (test->stored, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); +} + +static void +test_remove_from_stored (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored"); + test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish"); + test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, + "subscribe"); + + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->stored), + test->sjoerd)); + + g_array_append_val (test->arr, test->sjoerd); + tp_cli_channel_interface_group_run_remove_members (test->stored, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); + + /* by the time the method returns, we should have had the + * removal-notification, too */ + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->stored), + test->sjoerd)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->subscribe), + test->sjoerd)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->sjoerd)); +} + +static void +test_remove_from_stored_no_op (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->stored)), + ==, 8); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->stored), + test->ninja)); + + g_array_append_val (test->arr, test->ninja); + tp_cli_channel_interface_group_run_remove_members (test->stored, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); +} + +static void +test_accept_subscribe_request (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe"); + test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish"); + test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->subscribe)), + ==, 4); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->subscribe), + test->ninja)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->subscribe), + test->ninja)); + + /* the example CM's fake contacts accept requests that contain "please" */ + g_array_append_val (test->arr, test->ninja); + tp_cli_channel_interface_group_run_add_members (test->subscribe, + -1, test->arr, "Please may I see your presence?", &error, NULL); + g_assert_no_error (error); + + /* by the time the method returns, we should have had the + * change-notification, too */ + g_assert (tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->subscribe), + test->ninja)); + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->stored), + test->ninja)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->stored), + test->ninja)); + + /* after a short delay, the contact accepts our request */ + while (tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->subscribe), + test->ninja)) + g_main_context_iteration (NULL, TRUE); + + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->subscribe), + test->ninja)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->subscribe), + test->ninja)); + + /* the contact also requests our presence after a short delay */ + while (!tp_intset_is_member ( + tp_channel_group_get_local_pending (test->publish), + test->ninja)) + g_main_context_iteration (NULL, TRUE); + + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->ninja)); + g_assert (tp_intset_is_member ( + tp_channel_group_get_local_pending (test->publish), + test->ninja)); +} + +static void +test_reject_subscribe_request (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe"); + test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->subscribe)), + ==, 4); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->subscribe), + test->ninja)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->subscribe), + test->ninja)); + + /* the example CM's fake contacts reject requests that don't contain + * "please" */ + g_array_append_val (test->arr, test->ninja); + tp_cli_channel_interface_group_run_add_members (test->subscribe, + -1, test->arr, "I demand to see your presence", &error, NULL); + g_assert_no_error (error); + + /* by the time the method returns, we should have had the + * change-notification, too */ + g_assert (tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->subscribe), + test->ninja)); + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->stored), + test->ninja)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->stored), + test->ninja)); + + /* after a short delay, the contact rejects our request. Say please! */ + while (tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->subscribe), + test->ninja)) + g_main_context_iteration (NULL, TRUE); + + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->subscribe), + test->ninja)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->subscribe), + test->ninja)); + + /* the ninja is still on the stored list */ + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->stored), + test->ninja)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->stored), + test->ninja)); +} + +static void +test_remove_from_subscribe (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe"); + test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->subscribe)), + ==, 4); + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->subscribe), + test->sjoerd)); + + g_array_append_val (test->arr, test->sjoerd); + tp_cli_channel_interface_group_run_remove_members (test->subscribe, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); + + /* by the time the method returns, we should have had the + * removal-notification, too */ + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->subscribe), + test->sjoerd)); + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->stored), + test->sjoerd)); +} + +static void +test_remove_from_subscribe_pending (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe"); + test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_remote_pending (test->subscribe)), + ==, 2); + g_assert (tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->subscribe), + test->helen)); + + g_array_append_val (test->arr, test->helen); + tp_cli_channel_interface_group_run_remove_members (test->subscribe, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); + + /* by the time the method returns, we should have had the + * removal-notification, too */ + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->subscribe), + test->helen)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_remote_pending (test->subscribe), + test->helen)); + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->stored), + test->helen)); +} + +static void +test_remove_from_subscribe_no_op (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->subscribe)), + ==, 4); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->subscribe), + test->ninja)); + + g_array_append_val (test->arr, test->ninja); + tp_cli_channel_interface_group_run_remove_members (test->subscribe, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); +} + +static void +test_add_to_group (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP, + "Cambridge"); + test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored"); + test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish"); + test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, + "subscribe"); + + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->group)), + ==, 4); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->group), + test->ninja)); + + g_array_append_val (test->arr, test->ninja); + tp_cli_channel_interface_group_run_add_members (test->group, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); + + /* by the time the method returns, we should have had the + * change-notification, too */ + g_assert_cmpuint ( + tp_intset_size (tp_channel_group_get_members (test->group)), + ==, 5); + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->group), + test->ninja)); + + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->stored), + test->ninja)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->subscribe), + test->ninja)); + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->publish), + test->ninja)); +} + +static void +test_add_to_group_no_op (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP, + "Cambridge"); + + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->group), + test->sjoerd)); + + g_array_append_val (test->arr, test->sjoerd); + tp_cli_channel_interface_group_run_add_members (test->group, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); +} + +static void +test_remove_from_group (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP, + "Cambridge"); + + g_assert (tp_intset_is_member ( + tp_channel_group_get_members (test->group), + test->sjoerd)); + + g_array_append_val (test->arr, test->sjoerd); + tp_cli_channel_interface_group_run_remove_members (test->group, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); + + /* by the time the method returns, we should have had the + * removal-notification, too */ + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->group), + test->sjoerd)); +} + +static void +test_remove_from_group_no_op (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP, + "Cambridge"); + + g_assert (!tp_intset_is_member ( + tp_channel_group_get_members (test->group), + test->ninja)); + + g_array_append_val (test->arr, test->ninja); + tp_cli_channel_interface_group_run_remove_members (test->group, + -1, test->arr, "", &error, NULL); + g_assert_no_error (error); +} + +static void +test_remove_group (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP, + "Cambridge"); + + g_assert (!tp_intset_is_empty ( + tp_channel_group_get_members (test->group))); + + tp_cli_channel_run_close (test->group, -1, &error, NULL); + g_assert_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE); +} + +static void +test_remove_group_non_empty (Test *test, + gconstpointer nil G_GNUC_UNUSED) +{ + GError *error = NULL; + + test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP, + "people who understand const in C"); + + g_assert (tp_intset_is_empty ( + tp_channel_group_get_members (test->group))); + + tp_cli_channel_run_close (test->group, -1, &error, NULL); + g_assert_no_error (error); +} + +int +main (int argc, + char **argv) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add ("/contact-lists/nothing", + Test, NULL, setup, test_nothing, teardown); + + g_test_add ("/contact-lists/initial-channels", + Test, NULL, setup, test_initial_channels, teardown); + g_test_add ("/contact-lists/accept-publish-request", + Test, NULL, setup, test_accept_publish_request, teardown); + g_test_add ("/contact-lists/reject-publish-request", + Test, NULL, setup, test_reject_publish_request, teardown); + g_test_add ("/contact-lists/add-to-publish/invalid", + Test, NULL, setup, test_add_to_publish_invalid, teardown); + g_test_add ("/contact-lists/add-to-publish/no-op", + Test, NULL, setup, test_add_to_publish_no_op, teardown); + g_test_add ("/contact-lists/remove-from-publish", + Test, NULL, setup, test_remove_from_publish, teardown); + g_test_add ("/contact-lists/remove-from-publish/no-op", + Test, NULL, setup, test_remove_from_publish_no_op, teardown); + g_test_add ("/contact-lists/add-to-stored", + Test, NULL, setup, test_add_to_stored, teardown); + g_test_add ("/contact-lists/add-to-stored/no-op", + Test, NULL, setup, test_add_to_stored_no_op, teardown); + g_test_add ("/contact-lists/remove-from-stored", + Test, NULL, setup, test_remove_from_stored, teardown); + g_test_add ("/contact-lists/remove-from-stored/no-op", + Test, NULL, setup, test_remove_from_stored_no_op, teardown); + g_test_add ("/contact-lists/accept-subscribe-request", + Test, NULL, setup, test_accept_subscribe_request, teardown); + g_test_add ("/contact-lists/reject-subscribe-request", + Test, NULL, setup, test_reject_subscribe_request, teardown); + g_test_add ("/contact-lists/remove-from-subscribe", + Test, NULL, setup, test_remove_from_subscribe, teardown); + g_test_add ("/contact-lists/remove-from-subscribe/pending", + Test, NULL, setup, test_remove_from_subscribe_pending, teardown); + g_test_add ("/contact-lists/remove-from-subscribe/no-op", + Test, NULL, setup, test_remove_from_subscribe_no_op, teardown); + + g_test_add ("/contact-lists/add-to-group", + Test, NULL, setup, test_add_to_group, teardown); + g_test_add ("/contact-lists/add-to-group/no-op", + Test, NULL, setup, test_add_to_group_no_op, teardown); + g_test_add ("/contact-lists/remove-from-group", + Test, NULL, setup, test_remove_from_group, teardown); + g_test_add ("/contact-lists/remove-from-group/no-op", + Test, NULL, setup, test_remove_from_group_no_op, teardown); + g_test_add ("/contact-lists/remove-group", + Test, NULL, setup, test_remove_group, teardown); + g_test_add ("/contact-lists/remove-group/non-empty", + Test, NULL, setup, test_remove_group_non_empty, teardown); + + return g_test_run (); +} diff --git a/tests/lib/util.c b/tests/lib/util.c index 688725a6..5e24eb8f 100644 --- a/tests/lib/util.c +++ b/tests/lib/util.c @@ -10,6 +10,43 @@ #include "tests/lib/util.h" +void +test_proxy_run_until_prepared (gpointer proxy, + const GQuark *features) +{ + GError *error = NULL; + + test_proxy_run_until_prepared_or_failed (proxy, features, &error); + g_assert_no_error (error); +} + +static void +prepared_cb (GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + GAsyncResult **result = user_data; + + *result = g_object_ref (res); +} + +gboolean +test_proxy_run_until_prepared_or_failed (gpointer proxy, + const GQuark *features, + GError **error) +{ + GAsyncResult *result = NULL; + + tp_proxy_prepare_async (proxy, features, prepared_cb, &result); + /* not synchronous */ + g_assert (result == NULL); + + while (result == NULL) + g_main_context_iteration (NULL, TRUE); + + return tp_proxy_prepare_finish (proxy, result, error); +} + static void conn_ready_cb (TpConnection *conn G_GNUC_UNUSED, const GError *error, diff --git a/tests/lib/util.h b/tests/lib/util.h index 65d0957d..12ecf047 100644 --- a/tests/lib/util.h +++ b/tests/lib/util.h @@ -24,6 +24,12 @@ void test_proxy_run_until_dbus_queue_processed (gpointer proxy); TpHandle test_connection_run_request_contact_handle (TpConnection *connection, const gchar *id); +void test_proxy_run_until_prepared (gpointer proxy, + const GQuark *features); +gboolean test_proxy_run_until_prepared_or_failed (gpointer proxy, + const GQuark *features, + GError **error); + void test_connection_run_until_ready (TpConnection *conn); void test_connection_manager_run_until_ready (TpConnectionManager *cm); void test_connection_manager_run_until_readying_fails (TpConnectionManager *cm, |