diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | telepathy-glib/connection-handles.c | 2 | ||||
-rw-r--r-- | telepathy-glib/connection-manager.c | 22 | ||||
-rw-r--r-- | telepathy-glib/connection.c | 7 | ||||
-rw-r--r-- | telepathy-glib/contact.c | 39 | ||||
-rw-r--r-- | telepathy-glib/handle-repo-dynamic.c | 6 | ||||
-rw-r--r-- | tests/dbus/Makefile.am | 3 | ||||
-rw-r--r-- | tests/dbus/contacts-bug-19101.c | 199 | ||||
-rw-r--r-- | tests/lib/Makefile.am | 2 | ||||
-rw-r--r-- | tests/lib/bug-19101-conn.c | 74 | ||||
-rw-r--r-- | tests/lib/bug-19101-conn.h | 51 |
11 files changed, 388 insertions, 18 deletions
diff --git a/.gitignore b/.gitignore index 11cd89850..6da86cfee 100644 --- a/.gitignore +++ b/.gitignore @@ -72,6 +72,7 @@ tests/dbus/test-connection-getinterfaces-failure tests/dbus/test-connection-handles tests/dbus/test-connection-inject-bug16307 tests/dbus/test-contacts +tests/dbus/test-contacts-bug-19101 tests/dbus/test-contacts-mixin tests/dbus/test-dbus tests/dbus/test-disconnection diff --git a/telepathy-glib/connection-handles.c b/telepathy-glib/connection-handles.c index 3d8647a05..395b1d6e0 100644 --- a/telepathy-glib/connection-handles.c +++ b/telepathy-glib/connection-handles.c @@ -399,7 +399,7 @@ hold_handles_context_free (gpointer p) * On success, the caller has one reference to each handle in @handles, which * may be released later with tp_connection_unref_handles(). If not * released, the handles will remain valid until @connection becomes invalid - * (signalled by TpProxy::invalidated). + * (signalled by #TpProxy::invalidated). * * For convenience, the handle type and handles requested by the caller are * passed through to this callback on success, so the caller does not have to diff --git a/telepathy-glib/connection-manager.c b/telepathy-glib/connection-manager.c index bbd9030b2..18dbe451d 100644 --- a/telepathy-glib/connection-manager.c +++ b/telepathy-glib/connection-manager.c @@ -1061,7 +1061,7 @@ tp_connection_manager_class_init (TpConnectionManagerClass *klass) TP_ERROR_PREFIX, TP_ERRORS, TP_TYPE_ERROR); /** - * TpConnectionManager::info-source: + * TpConnectionManager:info-source: * * Where we got the current information on supported protocols * (a #TpCMInfoSource). @@ -1075,7 +1075,7 @@ tp_connection_manager_class_init (TpConnectionManagerClass *klass) param_spec); /** - * TpConnectionManager::connection-manager: + * TpConnectionManager:connection-manager: * * The name of the connection manager, e.g. "gabble" (read-only). */ @@ -1088,7 +1088,7 @@ tp_connection_manager_class_init (TpConnectionManagerClass *klass) param_spec); /** - * TpConnectionManager::manager-file: + * TpConnectionManager:manager-file: * * The absolute path of the .manager file. If set to %NULL (the default), * the XDG data directories will be searched for a .manager file of the @@ -1105,7 +1105,7 @@ tp_connection_manager_class_init (TpConnectionManagerClass *klass) param_spec); /** - * TpConnectionManager::always-introspect: + * TpConnectionManager:always-introspect: * * If %TRUE, always introspect the connection manager as it comes online, * even if we already have its info from a .manager file. Default %FALSE. @@ -1118,7 +1118,7 @@ tp_connection_manager_class_init (TpConnectionManagerClass *klass) param_spec); /** - * TpConnectionManager::activated: + * TpConnectionManager:activated: * @self: the connection manager proxy * * Emitted when the connection manager's well-known name appears on the bus. @@ -1132,7 +1132,7 @@ tp_connection_manager_class_init (TpConnectionManagerClass *klass) G_TYPE_NONE, 0); /** - * TpConnectionManager::exited: + * TpConnectionManager:exited: * @self: the connection manager proxy * * Emitted when the connection manager's well-known name disappears from @@ -1147,7 +1147,7 @@ tp_connection_manager_class_init (TpConnectionManagerClass *klass) G_TYPE_NONE, 0); /** - * TpConnectionManager::got-info: + * TpConnectionManager:got-info: * @self: the connection manager proxy * @source: a #TpCMInfoSource * @@ -1165,13 +1165,15 @@ tp_connection_manager_class_init (TpConnectionManagerClass *klass) /** * tp_connection_manager_new: * @dbus: Proxy for the D-Bus daemon - * @name: The connection manager name - * @manager_filename: The #TpConnectionManager::manager-file property + * @name: The connection manager name (such as "gabble") + * @manager_filename: The #TpConnectionManager:manager-file property, which may + * (and generally should) be %NULL. * @error: used to return an error if %NULL is returned * * Convenience function to create a new connection manager proxy. * - * Returns: a new reference to a connection manager proxy + * Returns: a new reference to a connection manager proxy, or %NULL if @error + * is set. */ TpConnectionManager * tp_connection_manager_new (TpDBusDaemon *dbus, diff --git a/telepathy-glib/connection.c b/telepathy-glib/connection.c index 18af8d49b..d2c704650 100644 --- a/telepathy-glib/connection.c +++ b/telepathy-glib/connection.c @@ -52,9 +52,10 @@ * Compared with a simple proxy for method calls, they add the following * features: * - * * connection status tracking - * - * * calling GetInterfaces() automatically + * <itemizedlist> + * <listitem>connection status tracking</listitem> + * <listitem>calling GetInterfaces() automatically</listitem> + * </itemizedlist> * * Since: 0.7.1 */ diff --git a/telepathy-glib/contact.c b/telepathy-glib/contact.c index ceae418dd..faf99ec4a 100644 --- a/telepathy-glib/contact.c +++ b/telepathy-glib/contact.c @@ -37,6 +37,8 @@ * @see_also: #TpConnection * * #TpContact objects represent the contacts on a particular #TpConnection. + * + * Since: 0.7.18 */ /** @@ -58,6 +60,8 @@ * Those functions should be avoided in favour of using #TpContact, * tp_connection_hold_handles(), tp_connection_request_handles() and * tp_connection_get_contact_attributes(). + * + * Since: 0.7.18 */ struct _TpContactClass { @@ -84,6 +88,8 @@ struct _TpContact { * When requesting a #TpContact, library users specify the desired features; * the #TpContact code will only initialize state for those features, to * avoid unwanted D-Bus round-trips and signal connections. + * + * Since: 0.7.18 */ G_DEFINE_TYPE (TpContact, tp_contact, G_TYPE_OBJECT); @@ -139,6 +145,8 @@ struct _TpContactPrivate { * Returns: a borrowed reference to the #TpContact:connection * (it must be referenced with g_object_ref if it must remain valid * longer than the contact) + * + * Since: 0.7.18 */ TpConnection * tp_contact_get_connection (TpContact *self) @@ -164,6 +172,8 @@ tp_contact_get_connection (TpContact *self) * to the handle. * * Returns: the same handle as the #TpContact:handle property + * + * Since: 0.7.18 */ TpHandle tp_contact_get_handle (TpContact *self) @@ -182,6 +192,8 @@ tp_contact_get_handle (TpContact *self) * that, it must be copied with g_strdup(). * * Returns: the same non-%NULL identifier as the #TpContact:identifier property + * + * Since: 0.7.18 */ const gchar * tp_contact_get_identifier (TpContact *self) @@ -202,6 +214,8 @@ tp_contact_get_identifier (TpContact *self) * <!-- --> * * Returns: %TRUE if @self has been set up to track the feature @feature + * + * Since: 0.7.18 */ gboolean tp_contact_has_feature (TpContact *self, @@ -223,6 +237,8 @@ tp_contact_has_feature (TpContact *self, * longer than that, it must be copied with g_strdup(). * * Returns: the same non-%NULL alias as the #TpContact:alias + * + * Since: 0.7.18 */ const gchar * tp_contact_get_alias (TpContact *self) @@ -249,6 +265,8 @@ tp_contact_get_alias (TpContact *self) * * Returns: the same token as the #TpContact:avatar-token property * (possibly %NULL) + * + * Since: 0.7.18 */ const gchar * tp_contact_get_avatar_token (TpContact *self) @@ -270,6 +288,8 @@ tp_contact_get_avatar_token (TpContact *self) * Otherwise, return %TP_CONNECTION_PRESENCE_TYPE_UNSET. * * Returns: the same presence type as the #TpContact:presence-type property + * + * Since: 0.7.18 */ TpConnectionPresenceType tp_contact_get_presence_type (TpContact *self) @@ -291,6 +311,8 @@ tp_contact_get_presence_type (TpContact *self) * * Returns: the same non-%NULL status name as the #TpContact:presence-status * property + * + * Since: 0.7.18 */ const gchar * tp_contact_get_presence_status (TpContact *self) @@ -313,6 +335,8 @@ tp_contact_get_presence_status (TpContact *self) * * Returns: the same non-%NULL message as the #TpContact:presence-message * property + * + * Since: 0.7.18 */ const gchar * tp_contact_get_presence_message (TpContact *self) @@ -772,7 +796,8 @@ contacts_context_fail (ContactsContext *c, error, c->user_data, c->weak_object); return; case CB_BY_ID: - for (i = 0; i < c->request_ids->len; i++) + /* -1 because NULL terminator is explicit */ + for (i = 0; i < c->request_ids->len - 1; i++) { const gchar *id = g_ptr_array_index (c->request_ids, i); @@ -831,6 +856,8 @@ contacts_context_fail (ContactsContext *c, * @contacts will contain contact objects for those handles that were * valid (possibly none of them), and @invalid will contain the handles * that were not valid. + * + * Since: 0.7.18 */ /** @@ -875,6 +902,8 @@ contacts_context_fail (ContactsContext *c, * that were requested, mapped to a corresponding #GError (either one * indicating that the ID was invalid, if that was determined before the * fatal error occurred, or a copy of @error). + * + * Since: 0.7.18 */ /** @@ -897,6 +926,8 @@ contacts_context_fail (ContactsContext *c, * If an unrecoverable error occurs (for instance, if @connection becomes * disconnected) it is indicated by @error, but the contacts in @contacts * are still provided. + * + * Since: 0.7.18 */ @@ -1819,6 +1850,8 @@ contacts_get_attributes (ContactsContext *context) * manager doesn't support them - users of this method should have a static * list of features they would like to use if possible, and use it for all * connection managers. + * + * Since: 0.7.18 */ void tp_connection_get_contacts_by_handle (TpConnection *self, @@ -1916,6 +1949,8 @@ contacts_context_idle_continue (gpointer data) * manager doesn't support them - users of this method should have a static * list of features they would like to use if possible, and use it for all * connection managers. + * + * Since: 0.7.18 */ void tp_connection_upgrade_contacts (TpConnection *self, @@ -2125,6 +2160,8 @@ contacts_requested_handles (TpConnection *connection, * manager doesn't support them - users of this method should have a static * list of features they would like to use if possible, and use it for all * connection managers. + * + * Since: 0.7.18 */ void tp_connection_get_contacts_by_id (TpConnection *self, diff --git a/telepathy-glib/handle-repo-dynamic.c b/telepathy-glib/handle-repo-dynamic.c index 03558f4ee..6b0fd94dc 100644 --- a/telepathy-glib/handle-repo-dynamic.c +++ b/telepathy-glib/handle-repo-dynamic.c @@ -519,7 +519,7 @@ tp_dynamic_handle_repo_class_init (TpDynamicHandleRepoClass *klass) "handle-type"); /** - * TpDynamicHandleRepo::normalize-function: + * TpDynamicHandleRepo:normalize-function: * * An optional #TpDynamicHandleRepoNormalizeFunc used to validate and * normalize handle IDs. If %NULL (which is the default), any handle ID is @@ -535,10 +535,10 @@ tp_dynamic_handle_repo_class_init (TpDynamicHandleRepoClass *klass) param_spec); /** - * TpDynamicHandleRepo::default-normalize-context: + * TpDynamicHandleRepo:default-normalize-context: * * An optional default context given to the - * #TpDynamicHandleRepo::normalize-function if %NULL is passed as context to + * #TpDynamicHandleRepo:normalize-function if %NULL is passed as context to * the ensure or lookup functions, e.g. when RequestHandle is called via * D-Bus. The default is %NULL. */ diff --git a/tests/dbus/Makefile.am b/tests/dbus/Makefile.am index b914d76bc..6c013c68e 100644 --- a/tests/dbus/Makefile.am +++ b/tests/dbus/Makefile.am @@ -7,6 +7,7 @@ noinst_PROGRAMS = \ test-connection-inject-bug16307 \ test-connection-getinterfaces-failure \ test-contacts \ + test-contacts-bug-19101 \ test-contacts-mixin \ test-dbus \ test-disconnection \ @@ -41,6 +42,8 @@ test_connection_getinterfaces_failure_SOURCES = \ test_contacts_SOURCES = contacts.c +test_contacts_bug_19101_SOURCES = contacts-bug-19101.c + test_contacts_mixin_SOURCES = contacts-mixin.c test_finalized_in_invalidated_handler_SOURCES = \ diff --git a/tests/dbus/contacts-bug-19101.c b/tests/dbus/contacts-bug-19101.c new file mode 100644 index 000000000..50c11094b --- /dev/null +++ b/tests/dbus/contacts-bug-19101.c @@ -0,0 +1,199 @@ +/* Regression test for fd.o bug #19101. */ + +#include <telepathy-glib/connection.h> +#include <telepathy-glib/contact.h> +#include <telepathy-glib/dbus.h> +#include <telepathy-glib/debug.h> + +#include "tests/lib/bug-19101-conn.h" +#include "tests/lib/debug.h" +#include "tests/lib/myassert.h" +#include "tests/lib/util.h" + +static int fail = 0; + +static void +myassert_failed (void) +{ + fail = 1; +} + +typedef struct { + GMainLoop *loop; + GError *error /* initialized to 0 */; + GPtrArray *contacts; + gchar **good_ids; + GHashTable *bad_ids; +} Result; + +static void +finish (gpointer r) +{ + Result *result = r; + + g_main_loop_quit (result->loop); +} + +static void +by_id_cb (TpConnection *connection, + guint n_contacts, + TpContact * const *contacts, + const gchar * const *good_ids, + GHashTable *bad_ids, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + Result *result = user_data; + + g_assert (result->contacts == NULL); + g_assert (result->error == NULL); + g_assert (result->good_ids == NULL); + g_assert (result->bad_ids == NULL); + + if (error == NULL) + { + GHashTableIter iter; + gpointer key, value; + guint i; + + DEBUG ("got %u contacts and %u bad IDs", n_contacts, + g_hash_table_size (bad_ids)); + + result->bad_ids = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) g_error_free); + tp_g_hash_table_update (result->bad_ids, bad_ids, + (GBoxedCopyFunc) g_strdup, (GBoxedCopyFunc) g_error_copy); + + g_hash_table_iter_init (&iter, result->bad_ids); + + while (g_hash_table_iter_next (&iter, &key, &value)) + { + gchar *id = key; + GError *e = value; + + DEBUG ("bad ID %s: %s %u: %s", id, g_quark_to_string (e->domain), + e->code, e->message); + } + + result->good_ids = g_strdupv ((GStrv) good_ids); + + result->contacts = g_ptr_array_sized_new (n_contacts); + + for (i = 0; i < n_contacts; i++) + { + TpContact *contact = contacts[i]; + + DEBUG ("contact #%u: %p", i, contact); + DEBUG ("contact #%u we asked for ID %s", i, good_ids[i]); + DEBUG ("contact #%u we got ID %s", i, + tp_contact_get_identifier (contact)); + DEBUG ("contact #%u alias: %s", i, tp_contact_get_alias (contact)); + DEBUG ("contact #%u avatar token: %s", i, + tp_contact_get_avatar_token (contact)); + DEBUG ("contact #%u presence type: %u", i, + tp_contact_get_presence_type (contact)); + DEBUG ("contact #%u presence status: %s", i, + tp_contact_get_presence_status (contact)); + DEBUG ("contact #%u presence message: %s", i, + tp_contact_get_presence_message (contact)); + g_ptr_array_add (result->contacts, g_object_ref (contact)); + } + } + else + { + DEBUG ("got an error: %s %u: %s", g_quark_to_string (error->domain), + error->code, error->message); + result->error = g_error_copy (error); + } +} + +static void +test_by_id (TpConnection *client_conn) +{ + Result result = { g_main_loop_new (NULL, FALSE) }; + static const gchar * const ids[] = { "Alice", "Bob", "Not valid", "Chris", + "not valid either", NULL }; + + tp_connection_get_contacts_by_id (client_conn, + 2, ids, + 0, NULL, + by_id_cb, + &result, finish, NULL); + + g_main_loop_run (result.loop); + + MYASSERT (result.error != NULL, ": should fail as the CM is broken"); + MYASSERT_SAME_UINT (result.error->domain, TP_DBUS_ERRORS); + MYASSERT (result.error->code == TP_DBUS_ERROR_INCONSISTENT, + ": %i != %i", result.error->code, TP_DBUS_ERROR_INCONSISTENT); + + MYASSERT (result.contacts == NULL, ""); + MYASSERT (result.good_ids == NULL, ""); + MYASSERT (result.bad_ids == NULL, ""); + + /* clean up */ + g_main_loop_unref (result.loop); + g_error_free (result.error); +} + +int +main (int argc, + char **argv) +{ + TpDBusDaemon *dbus; + ContactsConnection *service_conn; + TpBaseConnection *service_conn_as_base; + gchar *name; + gchar *conn_path; + GError *error = NULL; + TpConnection *client_conn; + + /* Setup */ + + g_type_init (); + tp_debug_set_flags ("all"); + dbus = tp_dbus_daemon_new (tp_get_bus ()); + + DEBUG ("a"); + service_conn = CONTACTS_CONNECTION (g_object_new ( + BUG_19101_TYPE_CONNECTION, + "account", "me@example.com", + "protocol", "simple", + NULL)); + DEBUG ("b"); + service_conn_as_base = TP_BASE_CONNECTION (service_conn); + MYASSERT (service_conn != NULL, ""); + MYASSERT (service_conn_as_base != NULL, ""); + + MYASSERT (tp_base_connection_register (service_conn_as_base, "simple", + &name, &conn_path, &error), ""); + MYASSERT_NO_ERROR (error); + + client_conn = tp_connection_new (dbus, name, conn_path, &error); + MYASSERT (client_conn != NULL, ""); + MYASSERT_NO_ERROR (error); + MYASSERT (tp_connection_run_until_ready (client_conn, TRUE, &error, NULL), + ""); + MYASSERT_NO_ERROR (error); + + /* Tests */ + + test_by_id (client_conn); + + /* Teardown */ + + MYASSERT (tp_cli_connection_run_disconnect (client_conn, -1, &error, NULL), + ""); + MYASSERT_NO_ERROR (error); + g_object_unref (client_conn); + + service_conn_as_base = NULL; + g_object_unref (service_conn); + g_free (name); + g_free (conn_path); + + g_object_unref (dbus); + + return fail; +} diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index fe25a37e1..d2509ca39 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -1,6 +1,8 @@ noinst_LTLIBRARIES = libtp-glib-tests.la libtp_glib_tests_la_SOURCES = \ + bug-19101-conn.c \ + bug-19101-conn.h \ bug16307-conn.c \ bug16307-conn.h \ contacts-conn.c \ diff --git a/tests/lib/bug-19101-conn.c b/tests/lib/bug-19101-conn.c new file mode 100644 index 000000000..44b00f32b --- /dev/null +++ b/tests/lib/bug-19101-conn.c @@ -0,0 +1,74 @@ +/* + * bug-19101-conn.c - a broken connection to reproduce bug #19101 + * + * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 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 "bug-19101-conn.h" + +#include "debug.h" + +static void contacts_iface_init (gpointer g_iface, gpointer iface_data); + +G_DEFINE_TYPE_WITH_CODE (Bug19101Connection, bug_19101_connection, + CONTACTS_TYPE_CONNECTION, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS, + contacts_iface_init); + ) + +static void +bug_19101_connection_init (Bug19101Connection *self) +{ +} + +static void +bug_19101_connection_class_init (Bug19101ConnectionClass *klass) +{ +} + +/* A broken implementation of GetContactAttributes, which returns an empty dict + * of attributes for each handle. + */ +static void +bug_19101_connection_get_contact_attributes ( + TpSvcConnectionInterfaceContacts *iface, + const GArray *handles, + const char **interfaces, + gboolean hold, + DBusGMethodInvocation *context) +{ + GHashTable *result = g_hash_table_new_full (NULL, NULL, NULL, + (GDestroyNotify) g_hash_table_destroy); + guint i; + + DEBUG ("called; returning rubbish"); + + for (i = 0 ; i < handles->len ; i++) + { + TpHandle h= g_array_index (handles, TpHandle, i); + GHashTable *attr_hash = g_hash_table_new_full (NULL, NULL, NULL, NULL); + + g_hash_table_insert (result, GUINT_TO_POINTER(h), attr_hash); + } + + tp_svc_connection_interface_contacts_return_from_get_contact_attributes ( + context, result); + g_hash_table_unref (result); +} + +static void +contacts_iface_init (gpointer g_iface, gpointer iface_data) +{ + TpSvcConnectionInterfaceContactsClass *klass = + (TpSvcConnectionInterfaceContactsClass *) g_iface; + +#define IMPLEMENT(x) tp_svc_connection_interface_contacts_implement_##x ( \ + klass, bug_19101_connection_##x) + IMPLEMENT(get_contact_attributes); +#undef IMPLEMENT +} diff --git a/tests/lib/bug-19101-conn.h b/tests/lib/bug-19101-conn.h new file mode 100644 index 000000000..e12df4bc9 --- /dev/null +++ b/tests/lib/bug-19101-conn.h @@ -0,0 +1,51 @@ +/* + * bug-19101-conn.h - header for a broken connection to reproduce bug #19101 + * + * Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 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. + */ + +#ifndef TESTS_LIB_BUG_19101_CONN_H +#define TESTS_LIB_BUG_19101_CONN_H + +#include "contacts-conn.h" + +G_BEGIN_DECLS + +typedef struct _Bug19101Connection Bug19101Connection; +typedef struct _Bug19101ConnectionClass Bug19101ConnectionClass; + +struct _Bug19101ConnectionClass { + ContactsConnectionClass parent_class; +}; + +struct _Bug19101Connection { + ContactsConnection parent; +}; + +GType bug_19101_connection_get_type (void); + +/* TYPE MACROS */ +#define BUG_19101_TYPE_CONNECTION \ + (bug_19101_connection_get_type ()) +#define BUG_19101_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), BUG_19101_TYPE_CONNECTION, \ + Bug19101Connection)) +#define BUG_19101_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), BUG_19101_TYPE_CONNECTION, \ + Bug19101ConnectionClass)) +#define BUG_19101_IS_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), BUG_19101_TYPE_CONNECTION)) +#define BUG_19101_IS_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), BUG_19101_TYPE_CONNECTION)) +#define BUG_19101_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), BUG_19101_TYPE_CONNECTION, \ + Bug19101ConnectionClass)) + +G_END_DECLS + +#endif |