diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2010-12-08 14:27:03 +0000 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2010-12-08 14:27:05 +0000 |
commit | 9540d949db39138fdbaac45ff1efdd940152ecf3 (patch) | |
tree | 8770f80b7bb284ee01cbe275f591fd3373b021c5 | |
parent | 5565f1bede0539e5cb43702a5804fa03b652c6e3 (diff) | |
parent | 488446450a1cbdbbd276cad964237ae48279e83f (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.c | 77 | ||||
-rw-r--r-- | tests/dbus/contacts-slow-path.c | 276 | ||||
-rw-r--r-- | tests/dbus/contacts.c | 374 |
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 (); } |