diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | tests/dbus/Makefile.am | 6 | ||||
-rw-r--r-- | tests/dbus/connection-handles.c | 374 |
3 files changed, 381 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore index 07bcb4045..105778ba7 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,7 @@ tests/dbus/test-call-cancellation tests/dbus/test-channel-introspect tests/dbus/test-connection tests/dbus/test-connection-getinterfaces-failure +tests/dbus/test-connection-handles tests/dbus/test-connection-inject-bug16307 tests/dbus/test-dbus tests/dbus/test-disconnection diff --git a/tests/dbus/Makefile.am b/tests/dbus/Makefile.am index 2768b8522..edea6746a 100644 --- a/tests/dbus/Makefile.am +++ b/tests/dbus/Makefile.am @@ -2,6 +2,7 @@ noinst_PROGRAMS = \ test-call-cancellation \ test-channel-introspect \ test-connection \ + test-connection-handles \ test-connection-inject-bug16307 \ test-connection-getinterfaces-failure \ test-dbus \ @@ -29,6 +30,11 @@ test_connection_LDADD = \ ../lib/libtp-glib-tests.la test_connection_SOURCES = connection.c +test_connection_handles_LDADD = \ + $(TP_GLIB_LIBS) \ + ../lib/libtp-glib-tests.la +test_connection_handles_SOURCES = connection-handles.c + test_connection_inject_bug16307_LDADD = \ $(TP_GLIB_LIBS) \ ../lib/libtp-glib-tests.la diff --git a/tests/dbus/connection-handles.c b/tests/dbus/connection-handles.c new file mode 100644 index 000000000..37a8fa9a0 --- /dev/null +++ b/tests/dbus/connection-handles.c @@ -0,0 +1,374 @@ +/* Feature test for handle reference tracking. + * + * 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 <telepathy-glib/connection.h> +#include <telepathy-glib/dbus.h> +#include <telepathy-glib/debug.h> + +#include "tests/lib/debug.h" +#include "tests/lib/myassert.h" +#include "tests/lib/simple-conn.h" + +static int fail = 0; + +static void +myassert_failed (void) +{ + fail = 1; +} + +typedef struct { + GMainLoop *loop; + GError *error /* initialized to 0 */; + GArray *handles; + gchar **ids; +} Result; + +static void +requested (TpConnection *connection, + TpHandleType handle_type, + guint n_handles, + const TpHandle *handles, + const gchar * const *ids, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + Result *result = user_data; + + g_assert (result->ids == NULL); + g_assert (result->handles == NULL); + g_assert (result->error == NULL); + + if (error == NULL) + { + DEBUG ("got %u handles", n_handles); + result->ids = g_strdupv ((GStrv) ids); + result->handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), + n_handles); + g_array_append_vals (result->handles, handles, n_handles); + } + else + { + DEBUG ("got an error"); + result->error = g_error_copy (error); + } +} + +static void +held (TpConnection *connection, + TpHandleType handle_type, + guint n_handles, + const TpHandle *handles, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + Result *result = user_data; + + g_assert (result->ids == NULL); + g_assert (result->handles == NULL); + g_assert (result->error == NULL); + + if (error == NULL) + { + DEBUG ("got %u handles", n_handles); + result->handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), + n_handles); + g_array_append_vals (result->handles, handles, n_handles); + } + else + { + DEBUG ("got an error"); + result->error = g_error_copy (error); + } +} + +static void +finish (gpointer r) +{ + Result *result = r; + + g_main_loop_quit (result->loop); +} + +static gboolean +quit_when_idle (gpointer p) +{ + g_main_loop_quit (p); + return FALSE; +} + +/* + * Assert that RequestHandles + unref releases the handles. + */ +static void +test_request_and_release (SimpleConnection *service_conn, + TpConnection *client_conn) +{ + Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL }; + const gchar * const ids[] = { "alice", "bob", "chris", NULL }; + TpHandleRepoIface *service_repo = tp_base_connection_get_handles ( + (TpBaseConnection *) service_conn, TP_HANDLE_TYPE_CONTACT); + guint i; + + g_message (G_STRFUNC); + + /* request three handles */ + + tp_connection_request_handles (client_conn, -1, + TP_HANDLE_TYPE_CONTACT, ids, requested, &result, finish, NULL); + + g_main_loop_run (result.loop); + + MYASSERT_NO_ERROR (result.error); + MYASSERT (result.ids != NULL, ""); + MYASSERT (result.handles != NULL, ""); + + for (i = 0; i < 3; i++) + { + MYASSERT (result.ids[i] != NULL, " [%u]", i); + MYASSERT (!tp_strdiff (result.ids[i], ids[i]), " [%u] %s != %s", + i, result.ids[i], ids[i]); + } + + MYASSERT (result.ids[3] == NULL, ""); + + MYASSERT (result.handles->len == 3, ": %u != 3", result.handles->len); + + /* check that the service and the client agree */ + + MYASSERT (tp_handles_are_valid (service_repo, result.handles, FALSE, NULL), + ""); + + for (i = 0; i < 3; i++) + { + TpHandle handle = g_array_index (result.handles, TpHandle, i); + + MYASSERT (!tp_strdiff (tp_handle_inspect (service_repo, handle), ids[i]), + "%s != %s", tp_handle_inspect (service_repo, handle), ids[i]); + } + + /* release the handles */ + + tp_connection_unref_handles (client_conn, TP_HANDLE_TYPE_CONTACT, + result.handles->len, (const TpHandle *) result.handles->data); + + /* synchronize state of D-Bus connection */ + g_idle_add_full (G_PRIORITY_LOW, quit_when_idle, result.loop, NULL); + g_main_loop_run (result.loop); + tp_cli_connection_run_get_protocol (client_conn, -1, NULL, NULL, NULL); + + /* check that the handles have been released */ + + for (i = 0; i < 3; i++) + { + TpHandle handle = g_array_index (result.handles, TpHandle, i); + + MYASSERT (!tp_handle_is_valid (service_repo, handle, NULL), ""); + } + + /* clean up */ + + g_strfreev (result.ids); + g_array_free (result.handles, TRUE); + g_assert (result.error == NULL); + g_main_loop_unref (result.loop); +} + +/* + * Assert that RequestHandles + HoldHandles + unref does not release the + * handles, but a second unref does. + */ +static void +test_request_hold_release (SimpleConnection *service_conn, + TpConnection *client_conn) +{ + Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL }; + const gchar * const ids[] = { "alice", "bob", "chris", NULL }; + TpHandleRepoIface *service_repo = tp_base_connection_get_handles ( + (TpBaseConnection *) service_conn, TP_HANDLE_TYPE_CONTACT); + guint i; + GArray *saved_handles; + + g_message (G_STRFUNC); + + /* request three handles */ + + tp_connection_request_handles (client_conn, -1, + TP_HANDLE_TYPE_CONTACT, ids, requested, &result, finish, NULL); + + g_main_loop_run (result.loop); + + MYASSERT_NO_ERROR (result.error); + MYASSERT (result.ids != NULL, ""); + MYASSERT (result.handles != NULL, ""); + + for (i = 0; i < 3; i++) + { + MYASSERT (result.ids[i] != NULL, " [%u]", i); + MYASSERT (!tp_strdiff (result.ids[i], ids[i]), " [%u] %s != %s", + i, result.ids[i], ids[i]); + } + + MYASSERT (result.ids[3] == NULL, ""); + + MYASSERT (result.handles->len == 3, ": %u != 3", result.handles->len); + + /* check that the service and the client agree */ + + MYASSERT (tp_handles_are_valid (service_repo, result.handles, FALSE, NULL), + ""); + + for (i = 0; i < 3; i++) + { + TpHandle handle = g_array_index (result.handles, TpHandle, i); + + MYASSERT (!tp_strdiff (tp_handle_inspect (service_repo, handle), ids[i]), + "%s != %s", tp_handle_inspect (service_repo, handle), ids[i]); + } + + /* hold the handles */ + + g_strfreev (result.ids); + result.ids = NULL; + saved_handles = result.handles; + result.handles = NULL; + g_assert (result.error == NULL); + + tp_connection_hold_handles (client_conn, -1, + TP_HANDLE_TYPE_CONTACT, saved_handles->len, + (const TpHandle *) saved_handles->data, + held, &result, finish, NULL); + + g_main_loop_run (result.loop); + + MYASSERT_NO_ERROR (result.error); + MYASSERT (result.ids == NULL, ""); + MYASSERT (result.handles != NULL, ""); + + for (i = 0; i < 3; i++) + { + TpHandle want = g_array_index (saved_handles, TpHandle, i); + TpHandle got = g_array_index (result.handles, TpHandle, i); + + MYASSERT (want == got, "%u != %u", want, got); + } + + g_array_free (saved_handles, TRUE); + + /* unref the handles */ + + tp_connection_unref_handles (client_conn, TP_HANDLE_TYPE_CONTACT, + result.handles->len, (const TpHandle *) result.handles->data); + + /* synchronize state of D-Bus connection */ + g_idle_add_full (G_PRIORITY_LOW, quit_when_idle, result.loop, NULL); + g_main_loop_run (result.loop); + tp_cli_connection_run_get_protocol (client_conn, -1, NULL, NULL, NULL); + + /* check that the handles have not been released */ + + MYASSERT (tp_handles_are_valid (service_repo, result.handles, FALSE, NULL), + ""); + + for (i = 0; i < 3; i++) + { + TpHandle handle = g_array_index (result.handles, TpHandle, i); + + MYASSERT (!tp_strdiff (tp_handle_inspect (service_repo, handle), ids[i]), + "%s != %s", tp_handle_inspect (service_repo, handle), ids[i]); + } + + /* release the handles by unreffing them again */ + + tp_connection_unref_handles (client_conn, TP_HANDLE_TYPE_CONTACT, + result.handles->len, (const TpHandle *) result.handles->data); + + /* synchronize state of D-Bus connection */ + g_idle_add_full (G_PRIORITY_LOW, quit_when_idle, result.loop, NULL); + g_main_loop_run (result.loop); + tp_cli_connection_run_get_protocol (client_conn, -1, NULL, NULL, NULL); + + /* check that the handles have been released */ + + for (i = 0; i < 3; i++) + { + TpHandle handle = g_array_index (result.handles, TpHandle, i); + + MYASSERT (!tp_handle_is_valid (service_repo, handle, NULL), ""); + } + + /* clean up */ + + g_main_loop_unref (result.loop); + g_strfreev (result.ids); + g_array_free (result.handles, TRUE); + g_assert (result.error == NULL); +} + +int +main (int argc, + char **argv) +{ + TpDBusDaemon *dbus; + SimpleConnection *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 ()); + + service_conn = SIMPLE_CONNECTION (g_object_new ( + SIMPLE_TYPE_CONNECTION, + "account", "me@example.com", + "protocol", "simple", + NULL)); + 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_request_and_release (service_conn, client_conn); + test_request_hold_release (service_conn, client_conn); + + /* Teardown */ + + MYASSERT (tp_cli_connection_run_disconnect (client_conn, -1, &error, NULL), + ""); + MYASSERT_NO_ERROR (error); + + service_conn_as_base = NULL; + g_object_unref (service_conn); + g_free (name); + g_free (conn_path); + + g_object_unref (dbus); + + return fail; +} |