summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2010-12-08 14:27:03 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2010-12-08 14:27:05 +0000
commit9540d949db39138fdbaac45ff1efdd940152ecf3 (patch)
tree8770f80b7bb284ee01cbe275f591fd3373b021c5
parent5565f1bede0539e5cb43702a5804fa03b652c6e3 (diff)
parent488446450a1cbdbbd276cad964237ae48279e83f (diff)
Merge branch '012-contact' into telepathy-glib-0.12
Reviewed-by: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=32191
-rw-r--r--telepathy-glib/contact.c77
-rw-r--r--tests/dbus/contacts-slow-path.c276
-rw-r--r--tests/dbus/contacts.c374
3 files changed, 597 insertions, 130 deletions
diff --git a/telepathy-glib/contact.c b/telepathy-glib/contact.c
index 3ce936cb7..4f8c2bb1b 100644
--- a/telepathy-glib/contact.c
+++ b/telepathy-glib/contact.c
@@ -1016,6 +1016,9 @@ struct _ContactsContext {
* failed with InvalidHandle, or the RequestHandles call failed with
* NotAvailable */
guint next_index;
+
+ /* TRUE if all contacts already have IDs */
+ gboolean contacts_have_ids;
};
/* This code (and lots of telepathy-glib, really) won't work if this
@@ -1414,6 +1417,7 @@ contacts_held_handles (TpConnection *connection,
guint i;
g_assert (n_handles == c->handles->len);
+ g_assert (c->contacts->len == 0);
for (i = 0; i < c->handles->len; i++)
{
@@ -2765,9 +2769,10 @@ contacts_context_supports_iface (ContactsContext *context,
}
static void
-contacts_context_queue_features (ContactsContext *context,
- ContactFeatureFlags feature_flags)
+contacts_context_queue_features (ContactsContext *context)
{
+ ContactFeatureFlags feature_flags = context->wanted;
+
/* Start slow path for requested features that are not in
* ContactAttributeInterfaces */
@@ -2870,10 +2875,8 @@ contacts_got_attributes (TpConnection *connection,
i = 0;
- if (c->signature == CB_BY_HANDLE)
+ if (c->signature == CB_BY_HANDLE && c->contacts->len == 0)
{
- g_assert (c->contacts->len == 0);
-
while (i < c->handles->len)
{
TpHandle handle = g_array_index (c->handles, guint, i);
@@ -3095,15 +3098,28 @@ contacts_get_attributes (ContactsContext *context)
}
}
+ if (array->len == 0 &&
+ !(context->signature == CB_BY_HANDLE && context->contacts->len == 0) &&
+ context->contacts_have_ids)
+ {
+ /* We're not going to do anything useful: we're not holding/inspecting
+ * the handles, and we're not inspecting any extended interfaces
+ * either. Skip it. */
+ g_ptr_array_free (array, TRUE);
+ contacts_context_continue (context);
+ return;
+ }
+
g_ptr_array_add (array, NULL);
supported_interfaces = (const gchar **) g_ptr_array_free (array, FALSE);
- /* we want to hold the handles if and only if the call is by_handle -
- * for the other modes, we already have handles */
+ /* The Hold parameter is only true if we started from handles, and we don't
+ * already have all the contacts we need. */
context->refcount++;
tp_connection_get_contact_attributes (context->connection, -1,
context->handles->len, (const TpHandle *) context->handles->data,
- supported_interfaces, (context->signature == CB_BY_HANDLE),
+ supported_interfaces,
+ (context->signature == CB_BY_HANDLE && context->contacts->len == 0),
contacts_got_attributes,
context, contacts_context_unref, context->weak_object);
g_free (supported_interfaces);
@@ -3227,15 +3243,36 @@ tp_connection_get_contacts_by_handle (TpConnection *self,
if (contacts != NULL)
{
- /* We have already held/inspected handles, so we can skip that. */
+ ContactFeatureFlags minimal_feature_flags = 0xFFFFFFFF;
+
+ /* We have already held (and possibly inspected) handles, so we can
+ * skip that. */
+
+ context->contacts_have_ids = TRUE;
+
for (i = 0; i < n_handles; i++)
{
TpContact *contact = g_object_ref (g_ptr_array_index (contacts, i));
+ minimal_feature_flags &= contact->priv->has_features;
g_ptr_array_add (context->contacts, contact);
+
+ if (contact->priv->identifier == NULL)
+ context->contacts_have_ids = FALSE;
}
- contacts_context_queue_features (context, feature_flags);
+ /* This context won't need to retrieve any features that every
+ * contact in the list already has. */
+ context->wanted &= (~minimal_feature_flags);
+
+ /* We do need to retrieve any features that aren't there yet, though. */
+ if (tp_proxy_has_interface_by_id (self,
+ TP_IFACE_QUARK_CONNECTION_INTERFACE_CONTACTS))
+ {
+ g_queue_push_head (&context->todo, contacts_get_attributes);
+ }
+
+ contacts_context_queue_features (context);
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
contacts_context_idle_continue, context, contacts_context_unref);
@@ -3250,12 +3287,11 @@ tp_connection_get_contacts_by_handle (TpConnection *self,
/* we support the Contacts interface, so we can hold the handles and
* simultaneously inspect them. After that, we'll fill in any
* features that are necessary (this becomes a no-op if Contacts
- * gave us everything). */
- contacts_get_attributes (context);
- contacts_context_queue_features (context, feature_flags);
- /* we have one excess ref to the context because we create it,
- * and then contacts_get_attributes refs it */
- contacts_context_unref (context);
+ * will give us everything). */
+ g_queue_push_head (&context->todo, contacts_get_attributes);
+ contacts_context_queue_features (context);
+ g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+ contacts_context_idle_continue, context, contacts_context_unref);
return;
}
@@ -3265,7 +3301,7 @@ tp_connection_get_contacts_by_handle (TpConnection *self,
g_queue_push_head (&context->todo, contacts_inspect);
/* After that we'll get the features */
- contacts_context_queue_features (context, feature_flags);
+ contacts_context_queue_features (context);
/* but first, we need to hold onto them */
tp_connection_hold_handles (self, -1,
@@ -3328,6 +3364,7 @@ tp_connection_upgrade_contacts (TpConnection *self,
for (i = 0; i < n_contacts; i++)
{
g_return_if_fail (contacts[i]->priv->connection == self);
+ g_return_if_fail (contacts[i]->priv->identifier != NULL);
}
if (!get_feature_flags (n_features, features, &feature_flags))
@@ -3343,6 +3380,8 @@ tp_connection_upgrade_contacts (TpConnection *self,
g_array_append_val (context->handles, contacts[i]->priv->handle);
}
+ context->contacts_have_ids = TRUE;
+
g_assert (context->handles->len == n_contacts);
if (tp_proxy_has_interface_by_id (self,
@@ -3351,7 +3390,7 @@ tp_connection_upgrade_contacts (TpConnection *self,
g_queue_push_head (&context->todo, contacts_get_attributes);
}
- contacts_context_queue_features (context, feature_flags);
+ contacts_context_queue_features (context);
/* use an idle to make sure the callback is called after we return,
* even if all the contacts actually have all the features, just to be
@@ -3570,7 +3609,7 @@ tp_connection_get_contacts_by_id (TpConnection *self,
g_queue_push_head (&context->todo, contacts_inspect);
}
- contacts_context_queue_features (context, feature_flags);
+ contacts_context_queue_features (context);
/* but first, we need to get the handles in the first place */
tp_connection_request_handles (self, -1,
diff --git a/tests/dbus/contacts-slow-path.c b/tests/dbus/contacts-slow-path.c
index c84400c0c..eb778eefc 100644
--- a/tests/dbus/contacts-slow-path.c
+++ b/tests/dbus/contacts-slow-path.c
@@ -21,6 +21,12 @@
#include "tests/lib/util.h"
typedef struct {
+ TpBaseConnection *base_connection;
+ TpTestsContactsConnection *legacy_service_conn;
+ TpConnection *legacy_client_conn;
+} Fixture;
+
+typedef struct {
GMainLoop *loop;
GError *error /* initialized to 0 */;
GPtrArray *contacts;
@@ -30,6 +36,18 @@ typedef struct {
} Result;
static void
+reset_result (Result *result)
+{
+ /* clean up before doing the second request */
+ g_array_free (result->invalid, TRUE);
+ result->invalid = NULL;
+ g_ptr_array_foreach (result->contacts, (GFunc) g_object_unref, NULL);
+ g_ptr_array_free (result->contacts, TRUE);
+ result->contacts = NULL;
+ g_clear_error (&result->error);
+}
+
+static void
by_handle_cb (TpConnection *connection,
guint n_contacts,
TpContact * const *contacts,
@@ -93,9 +111,11 @@ finish (gpointer r)
}
static void
-test_by_handle (TpTestsContactsConnection *service_conn,
- TpConnection *client_conn)
+test_by_handle (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpTestsContactsConnection *service_conn = f->legacy_service_conn;
+ TpConnection *client_conn = f->legacy_client_conn;
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
TpHandle handles[5] = { 0, 0, 0, 0, 0 };
TpHandleRepoIface *service_repo = tp_base_connection_get_handles (
@@ -232,9 +252,11 @@ test_by_handle (TpTestsContactsConnection *service_conn,
}
static void
-test_no_features (TpTestsContactsConnection *service_conn,
- TpConnection *client_conn)
+test_no_features (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpTestsContactsConnection *service_conn = f->legacy_service_conn;
+ TpConnection *client_conn = f->legacy_client_conn;
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
const gchar * const ids[] = { "alice", "bob", "chris" };
TpHandle handles[3] = { 0, 0, 0 };
@@ -365,9 +387,11 @@ upgrade_cb (TpConnection *connection,
} G_STMT_END
static void
-test_upgrade (TpTestsContactsConnection *service_conn,
- TpConnection *client_conn)
+test_upgrade (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpTestsContactsConnection *service_conn = f->legacy_service_conn;
+ TpConnection *client_conn = f->legacy_client_conn;
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
TpHandle handles[] = { 0, 0, 0 };
static const gchar * const ids[] = { "alice", "bob", "chris" };
@@ -587,9 +611,11 @@ contact_notify_cb (TpContact *contact,
}
static void
-test_features (TpTestsContactsConnection *service_conn,
- TpConnection *client_conn)
+test_features (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpTestsContactsConnection *service_conn = f->legacy_service_conn;
+ TpConnection *client_conn = f->legacy_client_conn;
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
TpHandle handles[] = { 0, 0, 0 };
static const gchar * const ids[] = { "alice", "bob", "chris" };
@@ -897,8 +923,10 @@ by_id_cb (TpConnection *connection,
}
static void
-test_by_id (TpConnection *client_conn)
+test_by_id (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpConnection *client_conn = f->legacy_client_conn;
Result result = { g_main_loop_new (NULL, FALSE) };
static const gchar * const ids[] = { "Alice", "Bob", "Not valid", "Chris",
"not valid either", NULL };
@@ -1022,40 +1050,218 @@ test_by_id (TpConnection *client_conn)
result.bad_ids = NULL;
}
-int
-main (int argc,
- char **argv)
+static void
+test_by_handle_again (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
- TpBaseConnection *base_connection;
- TpTestsContactsConnection *legacy_service_conn;
- GError *error = NULL;
- TpConnection *legacy_client_conn;
+ Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
+ TpHandle handle;
+ TpHandleRepoIface *service_repo = tp_base_connection_get_handles (
+ f->base_connection, TP_HANDLE_TYPE_CONTACT);
+ TpContact *contact;
+ gpointer weak_pointer;
+ const gchar *alias = "Alice in Wonderland";
+ TpContactFeature feature = TP_CONTACT_FEATURE_ALIAS;
+ gboolean ok;
+
+ g_test_bug ("25181");
+
+ handle = tp_handle_ensure (service_repo, "alice", NULL, NULL);
+ g_assert_cmpuint (handle, !=, 0);
+ tp_tests_contacts_connection_change_aliases (f->legacy_service_conn, 1,
+ &handle, &alias);
+
+ tp_connection_get_contacts_by_handle (f->legacy_client_conn,
+ 1, &handle,
+ 1, &feature,
+ by_handle_cb,
+ &result, finish, NULL);
+ g_main_loop_run (result.loop);
+ g_assert_cmpuint (result.contacts->len, ==, 1);
+ g_assert_cmpuint (result.invalid->len, ==, 0);
+ g_assert_no_error (result.error);
- /* Setup */
+ g_assert (g_ptr_array_index (result.contacts, 0) != NULL);
+ contact = g_object_ref (g_ptr_array_index (result.contacts, 0));
+ g_assert_cmpuint (tp_contact_get_handle (contact), ==, handle);
+ g_assert_cmpstr (tp_contact_get_identifier (contact), ==, "alice");
+ g_assert_cmpstr (tp_contact_get_alias (contact), ==, "Alice in Wonderland");
- g_type_init ();
- tp_debug_set_flags ("all");
+ /* clean up before doing the second request */
+ reset_result (&result);
+ g_assert (result.error == NULL);
- tp_tests_create_and_connect_conn (TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION,
- "me@test.com", &base_connection, &legacy_client_conn);
+ /* silently remove the object from D-Bus, so that if the second request
+ * makes any D-Bus calls, it will fail (but the client conn isn't
+ * invalidated) */
+ tp_dbus_daemon_unregister_object (
+ tp_base_connection_get_dbus_daemon (f->base_connection),
+ f->base_connection);
+ /* check that that worked */
+ ok = tp_cli_connection_run_get_self_handle (f->legacy_client_conn, -1, NULL,
+ &result.error, NULL);
+ g_assert_error (result.error, DBUS_GERROR, DBUS_GERROR_UNKNOWN_METHOD);
+ g_assert (!ok);
+ g_clear_error (&result.error);
+
+ tp_connection_get_contacts_by_handle (f->legacy_client_conn,
+ 1, &handle,
+ 1, &feature,
+ by_handle_cb,
+ &result, finish, NULL);
+ g_main_loop_run (result.loop);
+ g_assert_cmpuint (result.contacts->len, ==, 1);
+ g_assert_cmpuint (result.invalid->len, ==, 0);
+ g_assert_no_error (result.error);
+
+ g_assert (g_ptr_array_index (result.contacts, 0) == contact);
+ g_assert_cmpstr (tp_contact_get_alias (contact), ==, "Alice in Wonderland");
+
+ /* OK, put it back so teardown() can use it */
+ tp_dbus_daemon_register_object (
+ tp_base_connection_get_dbus_daemon (f->base_connection),
+ f->base_connection->object_path, f->base_connection);
+ /* check that *that* worked */
+ ok = tp_cli_connection_run_get_self_handle (f->legacy_client_conn, -1, NULL,
+ &result.error, NULL);
+ g_assert_no_error (result.error);
+ g_assert (ok);
+
+ g_assert (result.error == NULL);
+ reset_result (&result);
- legacy_service_conn = TP_TESTS_CONTACTS_CONNECTION (base_connection);
+ weak_pointer = contact;
+ g_object_add_weak_pointer ((GObject *) contact, &weak_pointer);
+ g_object_unref (contact);
+ g_assert (weak_pointer == NULL);
- /* Tests */
- test_by_handle (legacy_service_conn, legacy_client_conn);
- test_no_features (legacy_service_conn, legacy_client_conn);
- test_features (legacy_service_conn, legacy_client_conn);
- test_upgrade (legacy_service_conn, legacy_client_conn);
- test_by_id (legacy_client_conn);
+ tp_tests_proxy_run_until_dbus_queue_processed (f->legacy_client_conn);
+ g_main_loop_unref (result.loop);
+}
- /* Teardown */
+static void
+test_by_handle_upgrade (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
+{
+ Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
+ TpHandle handle;
+ TpHandleRepoIface *service_repo = tp_base_connection_get_handles (
+ f->base_connection, TP_HANDLE_TYPE_CONTACT);
+ TpContact *contact;
+ gpointer weak_pointer;
+ const gchar *alias = "Alice in Wonderland";
+ TpContactFeature feature = TP_CONTACT_FEATURE_ALIAS;
- MYASSERT (tp_cli_connection_run_disconnect (legacy_client_conn, -1, &error,
- NULL), "");
- g_assert_no_error (error);
+ g_test_bug ("32191");
- g_object_unref (legacy_client_conn);
- g_object_unref (legacy_service_conn);
+ handle = tp_handle_ensure (service_repo, "alice", NULL, NULL);
+ g_assert_cmpuint (handle, !=, 0);
+ tp_tests_contacts_connection_change_aliases (f->legacy_service_conn,
+ 1, &handle, &alias);
- return 0;
+ tp_connection_get_contacts_by_handle (f->legacy_client_conn,
+ 1, &handle,
+ 0, NULL,
+ by_handle_cb,
+ &result, finish, NULL);
+ g_main_loop_run (result.loop);
+ g_assert_cmpuint (result.contacts->len, ==, 1);
+ g_assert_cmpuint (result.invalid->len, ==, 0);
+ g_assert_no_error (result.error);
+
+ g_assert (g_ptr_array_index (result.contacts, 0) != NULL);
+ contact = g_object_ref (g_ptr_array_index (result.contacts, 0));
+ g_assert_cmpuint (tp_contact_get_handle (contact), ==, handle);
+ g_assert_cmpstr (tp_contact_get_identifier (contact), ==, "alice");
+ /* fallback alias is still in effect */
+ g_assert_cmpstr (tp_contact_get_alias (contact), ==, "alice");
+
+ /* clean up before doing the second request */
+ reset_result (&result);
+ g_assert (result.error == NULL);
+
+ /* the second request enables the Alias feature, so it must make more D-Bus
+ * round trips */
+ tp_connection_get_contacts_by_handle (f->legacy_client_conn,
+ 1, &handle,
+ 1, &feature,
+ by_handle_cb,
+ &result, finish, NULL);
+ g_main_loop_run (result.loop);
+ g_assert_cmpuint (result.contacts->len, ==, 1);
+ g_assert_cmpuint (result.invalid->len, ==, 0);
+ g_assert_no_error (result.error);
+
+ g_assert (g_ptr_array_index (result.contacts, 0) == contact);
+ g_assert_cmpstr (tp_contact_get_alias (contact), ==, "Alice in Wonderland");
+
+ g_assert (result.error == NULL);
+ reset_result (&result);
+
+ weak_pointer = contact;
+ g_object_add_weak_pointer ((GObject *) contact, &weak_pointer);
+ g_object_unref (contact);
+ g_assert (weak_pointer == NULL);
+
+ tp_tests_proxy_run_until_dbus_queue_processed (f->legacy_client_conn);
+ g_main_loop_unref (result.loop);
+}
+
+static void
+setup (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
+{
+ tp_tests_create_and_connect_conn (TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION,
+ "me@test.com", &f->base_connection, &f->legacy_client_conn);
+
+ f->legacy_service_conn = g_object_ref (TP_TESTS_CONTACTS_CONNECTION (
+ f->base_connection));
+}
+
+static void
+teardown (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
+{
+ GError *error = NULL;
+ gboolean ok;
+
+ if (f->legacy_client_conn != NULL)
+ {
+ ok = tp_cli_connection_run_disconnect (f->legacy_client_conn, -1,
+ &error, NULL);
+ g_assert_no_error (error);
+ g_assert (ok);
+ }
+
+ tp_clear_object (&f->legacy_client_conn);
+ tp_clear_object (&f->legacy_service_conn);
+ tp_clear_object (&f->base_connection);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ g_type_init ();
+ tp_debug_set_flags ("all");
+ g_set_prgname ("contacts-slow-path");
+ g_test_init (&argc, &argv, NULL);
+ g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
+
+ g_test_add ("/contacts-slow-path/by-handle", Fixture, NULL, setup,
+ test_by_handle, teardown);
+ g_test_add ("/contacts-slow-path/no-features", Fixture, NULL, setup,
+ test_no_features, teardown);
+ g_test_add ("/contacts-slow-path/features", Fixture, NULL, setup,
+ test_features, teardown);
+ g_test_add ("/contacts-slow-path/upgrade", Fixture, NULL, setup,
+ test_upgrade, teardown);
+ g_test_add ("/contacts-slow-path/by-id", Fixture, NULL, setup,
+ test_by_id, teardown);
+ g_test_add ("/contacts-slow-path/by-handle-again", Fixture, NULL, setup,
+ test_by_handle_again, teardown);
+ g_test_add ("/contacts-slow-path/by-handle-upgrade", Fixture, NULL, setup,
+ test_by_handle_upgrade, teardown);
+
+ return g_test_run ();
}
diff --git a/tests/dbus/contacts.c b/tests/dbus/contacts.c
index c36d45464..fd74f280f 100644
--- a/tests/dbus/contacts.c
+++ b/tests/dbus/contacts.c
@@ -30,6 +30,16 @@
#include "tests/lib/util.h"
typedef struct {
+ TpBaseConnection *base_connection;
+ TpBaseConnection *legacy_base_connection;
+ TpBaseConnection *no_requests_base_connection;
+ TpTestsContactsConnection *service_conn;
+ TpConnection *client_conn;
+ TpConnection *legacy_client_conn;
+ TpConnection *no_requests_client_conn;
+} Fixture;
+
+typedef struct {
GMainLoop *loop;
GError *error /* initialized to 0 */;
GPtrArray *contacts;
@@ -263,13 +273,16 @@ contact_info_request_cancel (gpointer cancellable)
}
static void
-test_contact_info (TpTestsContactsConnection *service_conn,
- TpConnection *client_conn)
+test_contact_info (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpTestsContactsConnection *service_conn = f->service_conn;
+ TpConnection *client_conn = f->client_conn;
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
TpHandleRepoIface *service_repo = tp_base_connection_get_handles (
(TpBaseConnection *) service_conn, TP_HANDLE_TYPE_CONTACT);
TpContactFeature features[] = { TP_CONTACT_FEATURE_CONTACT_INFO };
+ TpContact *self_contact;
TpContact *contact;
TpHandle handle;
const gchar *field_value[] = { "Foo", NULL };
@@ -301,6 +314,20 @@ test_contact_info (TpTestsContactsConnection *service_conn,
/* TEST2: Set contact info on the connection, then get the self TpContact.
* This tests the set operation works correctly and also test TpContact
* correctly introspects the ContactInfo when the feature is requested. */
+
+ /* ... but first, get the SelfHandle contact without any features (regression
+ * test for a related bug, fd.o #32191) */
+ handle = tp_connection_get_self_handle (client_conn);
+ tp_connection_get_contacts_by_handle (client_conn,
+ 1, &handle,
+ 0, NULL,
+ by_handle_cb,
+ &result, finish, NULL);
+ g_main_loop_run (result.loop);
+ g_assert_no_error (result.error);
+ self_contact = g_object_ref (g_ptr_array_index (result.contacts, 0));
+ reset_result (&result);
+
tp_connection_set_contact_info_async (client_conn, info_list,
contact_info_set_cb, &result);
g_main_loop_run (result.loop);
@@ -454,8 +481,10 @@ prepare_avatar_requirements_cb (GObject *object,
}
static void
-test_avatar_requirements (TpConnection *client_conn)
+test_avatar_requirements (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpConnection *client_conn = f->client_conn;
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
GQuark features[] = { TP_CONNECTION_FEATURE_AVATAR_REQUIREMENTS, 0 };
@@ -592,9 +621,11 @@ haze_remove_directory (const gchar *path)
#define RAND_STR_LEN 6
static void
-test_avatar_data (TpTestsContactsConnection *service_conn,
- TpConnection *client_conn)
+test_avatar_data (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpTestsContactsConnection *service_conn = f->service_conn;
+ TpConnection *client_conn = f->client_conn;
static const gchar letters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
gchar rand_str[RAND_STR_LEN + 1];
gchar *dir;
@@ -648,9 +679,11 @@ test_avatar_data (TpTestsContactsConnection *service_conn,
}
static void
-test_by_handle (TpTestsContactsConnection *service_conn,
- TpConnection *client_conn)
+test_by_handle (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpTestsContactsConnection *service_conn = f->service_conn;
+ TpConnection *client_conn = f->client_conn;
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
TpHandle handles[5] = { 0, 0, 0, 0, 0 };
TpHandleRepoIface *service_repo = tp_base_connection_get_handles (
@@ -786,9 +819,168 @@ test_by_handle (TpTestsContactsConnection *service_conn,
}
static void
-test_no_features (TpTestsContactsConnection *service_conn,
- TpConnection *client_conn)
+test_by_handle_again (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
+{
+ Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
+ TpHandle handle;
+ TpHandleRepoIface *service_repo = tp_base_connection_get_handles (
+ f->base_connection, TP_HANDLE_TYPE_CONTACT);
+ TpContact *contact;
+ gpointer weak_pointer;
+ const gchar *alias = "Alice in Wonderland";
+ TpContactFeature feature = TP_CONTACT_FEATURE_ALIAS;
+ gboolean ok;
+
+ g_test_bug ("25181");
+
+ handle = tp_handle_ensure (service_repo, "alice", NULL, NULL);
+ g_assert_cmpuint (handle, !=, 0);
+ tp_tests_contacts_connection_change_aliases (f->service_conn, 1, &handle,
+ &alias);
+
+ tp_connection_get_contacts_by_handle (f->client_conn,
+ 1, &handle,
+ 1, &feature,
+ by_handle_cb,
+ &result, finish, NULL);
+ g_main_loop_run (result.loop);
+ g_assert_cmpuint (result.contacts->len, ==, 1);
+ g_assert_cmpuint (result.invalid->len, ==, 0);
+ g_assert_no_error (result.error);
+
+ g_assert (g_ptr_array_index (result.contacts, 0) != NULL);
+ contact = g_object_ref (g_ptr_array_index (result.contacts, 0));
+ g_assert_cmpuint (tp_contact_get_handle (contact), ==, handle);
+ g_assert_cmpstr (tp_contact_get_identifier (contact), ==, "alice");
+ g_assert_cmpstr (tp_contact_get_alias (contact), ==, "Alice in Wonderland");
+
+ /* clean up before doing the second request */
+ reset_result (&result);
+ g_assert (result.error == NULL);
+
+ /* silently remove the object from D-Bus, so that if the second request
+ * makes any D-Bus calls, it will fail (but the client conn isn't
+ * invalidated) */
+ tp_dbus_daemon_unregister_object (
+ tp_base_connection_get_dbus_daemon (f->base_connection),
+ f->base_connection);
+ /* check that that worked */
+ ok = tp_cli_connection_run_get_self_handle (f->client_conn, -1, NULL,
+ &result.error, NULL);
+ g_assert_error (result.error, DBUS_GERROR, DBUS_GERROR_UNKNOWN_METHOD);
+ g_assert (!ok);
+ g_clear_error (&result.error);
+
+ tp_connection_get_contacts_by_handle (f->client_conn,
+ 1, &handle,
+ 1, &feature,
+ by_handle_cb,
+ &result, finish, NULL);
+ g_main_loop_run (result.loop);
+ g_assert_cmpuint (result.contacts->len, ==, 1);
+ g_assert_cmpuint (result.invalid->len, ==, 0);
+ g_assert_no_error (result.error);
+
+ g_assert (g_ptr_array_index (result.contacts, 0) == contact);
+ g_assert_cmpstr (tp_contact_get_alias (contact), ==, "Alice in Wonderland");
+
+ /* OK, put it back so teardown() can use it */
+ tp_dbus_daemon_register_object (
+ tp_base_connection_get_dbus_daemon (f->base_connection),
+ f->base_connection->object_path, f->base_connection);
+ /* check that *that* worked */
+ ok = tp_cli_connection_run_get_self_handle (f->client_conn, -1, NULL,
+ &result.error, NULL);
+ g_assert_no_error (result.error);
+ g_assert (ok);
+
+ g_assert (result.error == NULL);
+ reset_result (&result);
+
+ weak_pointer = contact;
+ g_object_add_weak_pointer ((GObject *) contact, &weak_pointer);
+ g_object_unref (contact);
+ g_assert (weak_pointer == NULL);
+
+ tp_tests_proxy_run_until_dbus_queue_processed (f->client_conn);
+ g_main_loop_unref (result.loop);
+}
+
+static void
+test_by_handle_upgrade (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
+{
+ Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
+ TpHandle handle;
+ TpHandleRepoIface *service_repo = tp_base_connection_get_handles (
+ f->base_connection, TP_HANDLE_TYPE_CONTACT);
+ TpContact *contact;
+ gpointer weak_pointer;
+ const gchar *alias = "Alice in Wonderland";
+ TpContactFeature feature = TP_CONTACT_FEATURE_ALIAS;
+
+ g_test_bug ("32191");
+
+ handle = tp_handle_ensure (service_repo, "alice", NULL, NULL);
+ g_assert_cmpuint (handle, !=, 0);
+ tp_tests_contacts_connection_change_aliases (f->service_conn, 1, &handle,
+ &alias);
+
+ tp_connection_get_contacts_by_handle (f->client_conn,
+ 1, &handle,
+ 0, NULL,
+ by_handle_cb,
+ &result, finish, NULL);
+ g_main_loop_run (result.loop);
+ g_assert_cmpuint (result.contacts->len, ==, 1);
+ g_assert_cmpuint (result.invalid->len, ==, 0);
+ g_assert_no_error (result.error);
+
+ g_assert (g_ptr_array_index (result.contacts, 0) != NULL);
+ contact = g_object_ref (g_ptr_array_index (result.contacts, 0));
+ g_assert_cmpuint (tp_contact_get_handle (contact), ==, handle);
+ g_assert_cmpstr (tp_contact_get_identifier (contact), ==, "alice");
+ /* fallback alias is still in effect */
+ g_assert_cmpstr (tp_contact_get_alias (contact), ==, "alice");
+
+ /* clean up before doing the second request */
+ reset_result (&result);
+ g_assert (result.error == NULL);
+
+ /* the second request enables the Alias feature, so it must make more D-Bus
+ * round trips */
+ tp_connection_get_contacts_by_handle (f->client_conn,
+ 1, &handle,
+ 1, &feature,
+ by_handle_cb,
+ &result, finish, NULL);
+ g_main_loop_run (result.loop);
+ g_assert_cmpuint (result.contacts->len, ==, 1);
+ g_assert_cmpuint (result.invalid->len, ==, 0);
+ g_assert_no_error (result.error);
+
+ g_assert (g_ptr_array_index (result.contacts, 0) == contact);
+ g_assert_cmpstr (tp_contact_get_alias (contact), ==, "Alice in Wonderland");
+
+ g_assert (result.error == NULL);
+ reset_result (&result);
+
+ weak_pointer = contact;
+ g_object_add_weak_pointer ((GObject *) contact, &weak_pointer);
+ g_object_unref (contact);
+ g_assert (weak_pointer == NULL);
+
+ tp_tests_proxy_run_until_dbus_queue_processed (f->client_conn);
+ g_main_loop_unref (result.loop);
+}
+
+static void
+test_no_features (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpTestsContactsConnection *service_conn = f->service_conn;
+ TpConnection *client_conn = f->client_conn;
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
const gchar * const ids[] = { "alice", "bob", "chris" };
TpHandle handles[3] = { 0, 0, 0 };
@@ -981,9 +1173,11 @@ create_contact_caps (TpHandle *handles)
}
static void
-test_upgrade (TpTestsContactsConnection *service_conn,
- TpConnection *client_conn)
+test_upgrade (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpTestsContactsConnection *service_conn = f->service_conn;
+ TpConnection *client_conn = f->client_conn;
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
TpHandle handles[] = { 0, 0, 0 };
static const gchar * const ids[] = { "alice", "bob", "chris" };
@@ -1246,9 +1440,11 @@ create_new_contact_caps (TpHandle *handles)
}
static void
-test_features (TpTestsContactsConnection *service_conn,
- TpConnection *client_conn)
+test_features (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpTestsContactsConnection *service_conn = f->service_conn;
+ TpConnection *client_conn = f->client_conn;
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
TpHandle handles[] = { 0, 0, 0 };
static const gchar * const ids[] = { "alice", "bob", "chris" };
@@ -1607,9 +1803,12 @@ by_id_cb (TpConnection *connection,
}
}
+
static void
-test_by_id (TpConnection *client_conn)
+test_by_id (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpConnection *client_conn = f->client_conn;
Result result = { g_main_loop_new (NULL, FALSE) };
static const gchar * const ids[] = { "Alice", "Bob", "Not valid", "Chris",
"not valid either", NULL };
@@ -1704,16 +1903,17 @@ test_by_id (TpConnection *client_conn)
g_main_loop_unref (result.loop);
}
+
static void
-test_capabilities_without_contact_caps (
- TpTestsContactsConnection *service_conn,
- TpConnection *client_conn)
+test_capabilities_without_contact_caps (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpConnection *client_conn = f->legacy_client_conn;
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
TpHandle handles[] = { 0, 0, 0 };
static const gchar * const ids[] = { "alice", "bob", "chris" };
TpHandleRepoIface *service_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) service_conn, TP_HANDLE_TYPE_CONTACT);
+ f->legacy_base_connection, TP_HANDLE_TYPE_CONTACT);
TpContact *contacts[3];
guint i;
TpContactFeature features[] = { TP_CONTACT_FEATURE_CAPABILITIES };
@@ -1766,16 +1966,17 @@ test_capabilities_without_contact_caps (
g_main_loop_unref (result.loop);
}
+
static void
-test_prepare_contact_caps_without_request (
- TpTestsContactsConnection *service_conn,
- TpConnection *client_conn)
+test_prepare_contact_caps_without_request (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
+ TpConnection *client_conn = f->no_requests_client_conn;
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
TpHandle handles[] = { 0, 0, 0 };
static const gchar * const ids[] = { "alice", "bob", "chris" };
TpHandleRepoIface *service_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) service_conn, TP_HANDLE_TYPE_CONTACT);
+ f->no_requests_base_connection, TP_HANDLE_TYPE_CONTACT);
TpContact *contacts[3];
guint i;
TpContactFeature features[] = { TP_CONTACT_FEATURE_CAPABILITIES };
@@ -1828,75 +2029,96 @@ test_prepare_contact_caps_without_request (
g_main_loop_unref (result.loop);
}
-int
-main (int argc,
- char **argv)
+static void
+setup (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
{
- TpBaseConnection *base_connection, *legacy_base_connection,
- *no_requests_base_connection;
- TpTestsContactsConnection *service_conn;
- GError *error = NULL;
- TpConnection *client_conn, *legacy_client_conn, *no_requests_client_conn;
-
- /* Setup */
-
- g_type_init ();
- tp_debug_set_flags ("all");
-
tp_tests_create_and_connect_conn (TP_TESTS_TYPE_CONTACTS_CONNECTION,
- "me@test.com", &base_connection, &client_conn);
+ "me@test.com", &f->base_connection, &f->client_conn);
- service_conn = TP_TESTS_CONTACTS_CONNECTION (base_connection);
+ f->service_conn = TP_TESTS_CONTACTS_CONNECTION (f->base_connection);
+ g_object_ref (f->service_conn);
tp_tests_create_and_connect_conn (TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION,
- "me2@test.com", &legacy_base_connection, &legacy_client_conn);
+ "me2@test.com", &f->legacy_base_connection, &f->legacy_client_conn);
tp_tests_create_and_connect_conn (TP_TESTS_TYPE_NO_REQUESTS_CONNECTION,
- "me3@test.com", &no_requests_base_connection, &no_requests_client_conn);
+ "me3@test.com", &f->no_requests_base_connection,
+ &f->no_requests_client_conn);
+}
- /* Tests */
+static void
+teardown (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
+{
+ gboolean ok;
+ GError *error = NULL;
+
+ if (f->client_conn != NULL)
+ {
+ ok = tp_cli_connection_run_disconnect (f->client_conn, -1, &error, NULL);
+ g_assert_no_error (error);
+ g_assert (ok);
+ }
- test_by_handle (service_conn, client_conn);
- test_no_features (service_conn, client_conn);
- test_features (service_conn, client_conn);
- test_upgrade (service_conn, client_conn);
- test_by_id (client_conn);
- test_avatar_requirements (client_conn);
- test_avatar_data (service_conn, client_conn);
- test_contact_info (service_conn, client_conn);
+ tp_clear_object (&f->client_conn);
+ tp_clear_object (&f->service_conn);
+ tp_clear_object (&f->base_connection);
+ if (f->legacy_client_conn != NULL)
+ {
+ ok = tp_cli_connection_run_disconnect (f->legacy_client_conn, -1, &error,
+ NULL);
+ g_assert_no_error (error);
+ g_assert (ok);
+ }
+
+ tp_clear_object (&f->legacy_client_conn);
+ tp_clear_object (&f->legacy_base_connection);
+
+ if (f->no_requests_client_conn != NULL)
+ {
+ ok = tp_cli_connection_run_disconnect (f->no_requests_client_conn, -1,
+ &error, NULL);
+ g_assert_no_error (error);
+ g_assert (ok);
+ }
+
+ tp_clear_object (&f->no_requests_client_conn);
+ tp_clear_object (&f->no_requests_base_connection);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ g_type_init ();
+ tp_debug_set_flags ("all");
+ g_set_prgname ("contacts");
+ g_test_init (&argc, &argv, NULL);
+ g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
+
+#define ADD(x) \
+ g_test_add ("/contacts/" #x, Fixture, NULL, setup, test_ ## x, teardown)
+
+ ADD (by_handle);
+ ADD (by_handle_again);
+ ADD (by_handle_upgrade);
+ ADD (no_features);
+ ADD (features);
+ ADD (upgrade);
+ ADD (by_id);
+ ADD (avatar_requirements);
+ ADD (avatar_data);
+ ADD (contact_info);
/* test if TpContact fallbacks to connection's capabilities if
* ContactCapabilities is not implemented. */
- test_capabilities_without_contact_caps (
- TP_TESTS_CONTACTS_CONNECTION (legacy_base_connection),
- legacy_client_conn);
+ ADD (capabilities_without_contact_caps);
/* test if TP_CONTACT_FEATURE_CAPABILITIES is prepared but with
* an empty set of capabilities if the connection doesn't support
* ContactCapabilities and Requests. */
- test_prepare_contact_caps_without_request (
- TP_TESTS_CONTACTS_CONNECTION (no_requests_base_connection),
- no_requests_client_conn);
-
- /* Teardown */
-
- MYASSERT (tp_cli_connection_run_disconnect (client_conn, -1, &error, NULL),
- "");
- g_assert_no_error (error);
- g_object_unref (client_conn);
- g_object_unref (service_conn);
-
- MYASSERT (tp_cli_connection_run_disconnect (legacy_client_conn, -1, &error, NULL),
- "");
- g_assert_no_error (error);
- g_object_unref (legacy_client_conn);
- g_object_unref (legacy_base_connection);
-
- MYASSERT (tp_cli_connection_run_disconnect (no_requests_client_conn, -1,
- &error, NULL), "");
- g_assert_no_error (error);
- g_object_unref (no_requests_client_conn);
- g_object_unref (no_requests_base_connection);
+ ADD (prepare_contact_caps_without_request);
- return 0;
+ return g_test_run ();
}