/* Feature test for https://bugs.freedesktop.org/show_bug.cgi?id=15300 * * Copyright (C) 2007-2008 Collabora Ltd. * 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. */ #include "config.h" #include #include #include #include #include #include "tests/lib/myassert.h" #include "tests/lib/simple-conn.h" #include "tests/lib/util.h" typedef struct { TpDBusDaemon *dbus; TpTestsSimpleConnection *service_conn; TpBaseConnection *service_conn_as_base; gchar *conn_name; gchar *conn_path; TpConnection *conn; gboolean cwr_ready; GError *cwr_error /* initialized in setup */; GAsyncResult *prepare_result; } Test; static GError invalidated_for_test = { 0, TP_ERROR_PERMISSION_DENIED, "No connection for you!" }; static void connection_prepared_cb (GObject *object, GAsyncResult *res, gpointer user_data) { Test *test = user_data; g_message ("%p prepared", object); g_assert (test->prepare_result == NULL); test->prepare_result = g_object_ref (res); } static void setup (Test *test, gconstpointer data) { GError *error = NULL; invalidated_for_test.domain = TP_ERROR; tp_debug_set_flags ("all"); test->dbus = tp_tests_dbus_daemon_dup_or_die (); test->service_conn = TP_TESTS_SIMPLE_CONNECTION ( tp_tests_object_new_static_class ( TP_TESTS_TYPE_SIMPLE_CONNECTION, "account", "me@example.com", "protocol", "simple-protocol", NULL)); test->service_conn_as_base = TP_BASE_CONNECTION (test->service_conn); g_assert (test->service_conn != NULL); g_assert (test->service_conn_as_base != NULL); g_assert (tp_base_connection_register (test->service_conn_as_base, "simple", &test->conn_name, &test->conn_path, &error)); g_assert_no_error (error); test->cwr_ready = FALSE; test->cwr_error = NULL; } static void teardown (Test *test, gconstpointer data) { TpConnection *conn; GError *error = NULL; if (test->conn != NULL) { g_object_unref (test->conn); test->conn = NULL; } /* disconnect the connection so we don't leak it */ conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path, &error); g_assert (conn != NULL); g_assert_no_error (error); tp_tests_connection_assert_disconnect_succeeds (conn); g_assert (!tp_connection_run_until_ready (conn, FALSE, &error, NULL)); g_assert_error (error, TP_ERROR, TP_ERROR_CANCELLED); g_clear_error (&error); test->service_conn_as_base = NULL; g_object_unref (test->service_conn); g_free (test->conn_name); g_free (test->conn_path); g_object_unref (test->dbus); test->dbus = NULL; } static void test_run_until_invalid (Test *test, gconstpointer nil G_GNUC_UNUSED) { GError *error = NULL; test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path, &error); g_assert (test->conn != NULL); g_assert_no_error (error); tp_proxy_invalidate ((TpProxy *) test->conn, &invalidated_for_test); MYASSERT (!tp_connection_run_until_ready (test->conn, TRUE, &error, NULL), ""); g_assert (error != NULL); g_assert_error (error, invalidated_for_test.domain, invalidated_for_test.code); g_assert_cmpstr (error->message, ==, invalidated_for_test.message); g_error_free (error); } static void test_run_until_ready (Test *test, gconstpointer nil G_GNUC_UNUSED) { GError *error = NULL; test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path, &error); g_assert (test->conn != NULL); g_assert_no_error (error); MYASSERT (tp_connection_run_until_ready (test->conn, TRUE, &error, NULL), ""); g_assert_no_error (error); } static void conn_ready (TpConnection *connection, const GError *error, gpointer user_data) { Test *test = user_data; test->cwr_ready = TRUE; if (error == NULL) { gboolean parsed; gchar *proto = NULL; gchar *cm_name = NULL; g_message ("connection %p ready", connection); parsed = tp_connection_parse_object_path (connection, &proto, &cm_name); g_assert (parsed); g_assert_cmpstr (proto, ==, "simple-protocol"); g_assert_cmpstr (cm_name, ==, "simple"); g_free (proto); g_free (cm_name); } else { g_message ("connection %p invalidated: %s #%u \"%s\"", connection, g_quark_to_string (error->domain), error->code, error->message); test->cwr_error = g_error_copy (error); } } static void test_prepare (Test *test, gconstpointer nil G_GNUC_UNUSED) { GError *error = NULL; GQuark features[] = { TP_CONNECTION_FEATURE_CONNECTED, TP_CONNECTION_FEATURE_CAPABILITIES, 0 }; TpConnectionStatusReason reason; TpCapabilities *caps; GPtrArray *classes; gchar *cm_name, *protocol_name; test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path, &error); g_assert (test->conn != NULL); g_assert_no_error (error); g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE)); g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CONNECTED)); tp_proxy_prepare_async (test->conn, NULL, connection_prepared_cb, test); /* this is not synchronous */ g_assert (test->prepare_result == NULL); g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE)); while (test->prepare_result == NULL) g_main_context_iteration (NULL, TRUE); g_assert (tp_proxy_prepare_finish (test->conn, test->prepare_result, &error)); g_assert_no_error (error); g_object_unref (test->prepare_result); test->prepare_result = NULL; g_assert (tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE)); g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CONNECTED)); g_assert_cmpuint (tp_connection_get_self_handle (test->conn), ==, 0); g_assert_cmpint (tp_connection_get_status (test->conn, NULL), ==, TP_CONNECTION_STATUS_DISCONNECTED); g_assert_cmpstr (tp_connection_get_cm_name (test->conn), ==, "simple"); g_assert_cmpstr (tp_connection_get_protocol_name (test->conn), ==, "simple-protocol"); g_object_get (test->conn, "cm-name", &cm_name, "protocol-name", &protocol_name, NULL); g_assert_cmpstr (cm_name, ==, "simple"); g_assert_cmpstr (protocol_name, ==, "simple-protocol"); g_free (cm_name); g_free (protocol_name); tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL); tp_proxy_prepare_async (test->conn, features, connection_prepared_cb, test); while (test->prepare_result == NULL) g_main_context_iteration (NULL, TRUE); g_assert (tp_proxy_prepare_finish (test->conn, test->prepare_result, &error)); g_assert_no_error (error); g_object_unref (test->prepare_result); test->prepare_result = NULL; g_assert (tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE)); g_assert (tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CONNECTED)); g_assert (tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CAPABILITIES)); g_assert_cmpuint (tp_connection_get_self_handle (test->conn), !=, 0); g_assert_cmpint (tp_connection_get_status (test->conn, &reason), ==, TP_CONNECTION_STATUS_CONNECTED); g_assert_cmpint (reason, ==, TP_CONNECTION_STATUS_REASON_REQUESTED); caps = tp_connection_get_capabilities (test->conn); g_assert (caps != NULL); classes = tp_capabilities_get_channel_classes (caps); g_assert (classes != NULL); g_assert_cmpint (classes->len, ==, 0); } static void test_fail_to_prepare (Test *test, gconstpointer nil G_GNUC_UNUSED) { GError *error = NULL; GQuark features[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 }; const GHashTable *asv; test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path, &error); g_assert (test->conn != NULL); g_assert_no_error (error); g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE)); g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CONNECTED)); tp_proxy_prepare_async (test->conn, NULL, connection_prepared_cb, test); tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL); tp_proxy_invalidate ((TpProxy *) test->conn, &invalidated_for_test); /* this is not synchronous */ g_assert (test->prepare_result == NULL); g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE)); while (test->prepare_result == NULL) g_main_context_iteration (NULL, TRUE); g_assert (!tp_proxy_prepare_finish (test->conn, test->prepare_result, &error)); g_assert_error (error, TP_ERROR, TP_ERROR_PERMISSION_DENIED); g_clear_error (&error); g_object_unref (test->prepare_result); test->prepare_result = NULL; g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE)); g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CONNECTED)); /* it's not synchronous even if we were already invalidated */ tp_proxy_prepare_async (test->conn, features, connection_prepared_cb, test); g_assert (test->prepare_result == NULL); while (test->prepare_result == NULL) g_main_context_iteration (NULL, TRUE); g_assert (!tp_proxy_prepare_finish (test->conn, test->prepare_result, &error)); g_assert_error (error, TP_ERROR, TP_ERROR_PERMISSION_DENIED); g_clear_error (&error); g_object_unref (test->prepare_result); test->prepare_result = NULL; g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE)); g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CONNECTED)); g_assert_cmpstr (tp_connection_get_detailed_error (test->conn, NULL), ==, TP_ERROR_STR_PERMISSION_DENIED); g_assert_cmpstr (tp_connection_get_detailed_error (test->conn, &asv), ==, TP_ERROR_STR_PERMISSION_DENIED); g_assert (asv != NULL); } static void test_call_when_ready (Test *test, gconstpointer nil G_GNUC_UNUSED) { GError *error = NULL; test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path, &error); g_assert (test->conn != NULL); g_assert_no_error (error); tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL); tp_connection_call_when_ready (test->conn, conn_ready, test); while (!test->cwr_ready) g_main_context_iteration (NULL, TRUE); g_assert_no_error (test->cwr_error); /* Connection already ready here, so we are called back synchronously */ test->cwr_ready = FALSE; test->cwr_error = NULL; tp_connection_call_when_ready (test->conn, conn_ready, test); g_assert_cmpint (test->cwr_ready, ==, TRUE); g_assert_no_error (test->cwr_error); } static void test_call_when_invalid (Test *test, gconstpointer nil G_GNUC_UNUSED) { GError *error = NULL; test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path, &error); g_assert (test->conn != NULL); g_assert_no_error (error); /* Connection becomes invalid, so we are called back synchronously */ tp_connection_call_when_ready (test->conn, conn_ready, test); tp_proxy_invalidate ((TpProxy *) test->conn, &invalidated_for_test); g_assert_cmpint (test->cwr_ready, ==, TRUE); g_assert_error (test->cwr_error, invalidated_for_test.domain, invalidated_for_test.code); g_assert_cmpstr (test->cwr_error->message, ==, invalidated_for_test.message); g_clear_error (&test->cwr_error); /* Connection already invalid, so we are called back synchronously */ test->cwr_ready = FALSE; test->cwr_error = NULL; tp_connection_call_when_ready (test->conn, conn_ready, test); g_assert (test->cwr_ready); g_assert_error (test->cwr_error, invalidated_for_test.domain, invalidated_for_test.code); g_assert_cmpstr (test->cwr_error->message, ==, invalidated_for_test.message); g_error_free (test->cwr_error); test->cwr_error = NULL; } static void test_object_path (Test *test, gconstpointer nil G_GNUC_UNUSED) { const gchar *invalid_path = TP_CONN_OBJECT_PATH_BASE "invalid"; const gchar *invalid_name = TP_CONN_BUS_NAME_BASE "invalid"; TpConnection *connection; GError *error = NULL; test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path, &error); g_assert (test->conn != NULL); g_assert_no_error (error); tp_tests_proxy_run_until_prepared (test->conn, NULL); g_assert_cmpstr (tp_connection_get_cm_name (test->conn), ==, "simple"); g_assert_cmpstr (tp_connection_get_protocol_name (test->conn), ==, "simple-protocol"); /* Register the same connection with an invalid object path */ tp_dbus_daemon_register_object (test->dbus, invalid_path, test->service_conn); tp_dbus_daemon_request_name (test->dbus, invalid_name, FALSE, &error); g_assert_no_error (error); /* Create a TpConnection for that path, it return invalidated connection */ connection = tp_connection_new (test->dbus, NULL, invalid_path, &error); g_assert (connection == NULL); g_assert_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_OBJECT_PATH); g_clear_error (&error); } int main (int argc, char **argv) { tp_tests_init (&argc, &argv); g_test_add ("/conn/prepare", Test, NULL, setup, test_prepare, teardown); g_test_add ("/conn/fail_to_prepare", Test, NULL, setup, test_fail_to_prepare, teardown); g_test_add ("/conn/run_until_invalid", Test, NULL, setup, test_run_until_invalid, teardown); g_test_add ("/conn/run_until_ready", Test, NULL, setup, test_run_until_ready, teardown); g_test_add ("/conn/call_when_ready", Test, NULL, setup, test_call_when_ready, teardown); g_test_add ("/conn/call_when_invalid", Test, NULL, setup, test_call_when_invalid, teardown); g_test_add ("/conn/object_path", Test, NULL, setup, test_object_path, teardown); return tp_tests_run_with_bus (); }