/* A very basic feature test for TpAccount * * Copyright (C) 2009-2012 Collabora Ltd. * Copyright (C) 2009 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/contacts-conn.h" #include "tests/lib/simple-account.h" #include "tests/lib/util.h" #define ACCOUNT_PATH TP_ACCOUNT_OBJECT_PATH_BASE "what/ev/er" #define SUPERSEDED_PATH TP_ACCOUNT_OBJECT_PATH_BASE "super/seded/whatever" static void test_parse_failure (gconstpointer test_data) { GError *error = NULL; g_assert (!tp_account_parse_object_path (test_data, NULL, NULL, NULL, &error)); g_assert (error != NULL); g_error_free (error); } typedef struct { const gchar *path; const gchar *cm; const gchar *protocol; const gchar *account_id; } TestParseData; static TestParseData * test_parse_data_new (const gchar *path, const gchar *cm, const gchar *protocol, const gchar *account_id) { TestParseData *t = g_slice_new (TestParseData); t->path = path; t->cm = cm; t->protocol = protocol; t->account_id = account_id; return t; } static void test_parse_success (gconstpointer test_data) { TestParseData *t = (TestParseData *) test_data; gchar *cm, *protocol, *account_id; GError *error = NULL; g_assert (tp_account_parse_object_path (t->path, &cm, &protocol, &account_id, &error)); g_assert_no_error (error); g_assert_cmpstr (cm, ==, t->cm); g_assert_cmpstr (protocol, ==, t->protocol); g_assert_cmpstr (account_id, ==, t->account_id); g_free (cm); g_free (protocol); g_free (account_id); g_slice_free (TestParseData, t); } typedef struct { GMainLoop *mainloop; TpDBusDaemon *dbus; TpAccount *account; gulong notify_id; /* g_strdup (property name) => GUINT_TO_POINTER (counter) */ GHashTable *times_notified; GAsyncResult *result; GError *error /* initialized where needed */; /* initialized in prepare_service */ TpTestsSimpleAccount *account_service; TpBaseConnection *conn1_service; TpBaseConnection *conn2_service; TpConnection *conn1; TpConnection *conn2; } Test; static void setup (Test *test, gconstpointer data) { test->mainloop = g_main_loop_new (NULL, FALSE); test->dbus = tp_tests_dbus_daemon_dup_or_die (); g_assert (test->dbus != NULL); test->account = NULL; test->times_notified = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); } static void setup_service (Test *test, gconstpointer data) { setup (test, data); tp_dbus_daemon_request_name (test->dbus, TP_ACCOUNT_MANAGER_BUS_NAME, FALSE, &test->error); g_assert_no_error (test->error); test->account_service = g_object_new (TP_TESTS_TYPE_SIMPLE_ACCOUNT, NULL); tp_dbus_daemon_register_object (test->dbus, ACCOUNT_PATH, test->account_service); tp_tests_create_and_connect_conn (TP_TESTS_TYPE_CONTACTS_CONNECTION, "what@ever", &test->conn1_service, &test->conn1); tp_tests_create_and_connect_conn (TP_TESTS_TYPE_CONTACTS_CONNECTION, "what2@ever", &test->conn2_service, &test->conn2); } static guint test_get_times_notified (Test *test, const gchar *property) { return GPOINTER_TO_UINT (g_hash_table_lookup (test->times_notified, property)); } static void test_notify_cb (Test *test, GParamSpec *pspec, TpAccount *account) { guint counter = test_get_times_notified (test, pspec->name); g_hash_table_insert (test->times_notified, g_strdup (pspec->name), GUINT_TO_POINTER (++counter)); } static void test_set_up_account_notify (Test *test) { g_assert (test->account != NULL); g_hash_table_remove_all (test->times_notified); if (test->notify_id != 0) { g_signal_handler_disconnect (test->account, test->notify_id); } test->notify_id = g_signal_connect_swapped (test->account, "notify", G_CALLBACK (test_notify_cb), test); } static void teardown (Test *test, gconstpointer data) { if (test->account != NULL) { tp_tests_proxy_run_until_dbus_queue_processed (test->account); if (test->notify_id != 0) { g_signal_handler_disconnect (test->account, test->notify_id); } g_object_unref (test->account); test->account = NULL; } g_hash_table_unref (test->times_notified); test->times_notified = NULL; /* make sure any pending calls on the account have happened, so it can die */ tp_tests_proxy_run_until_dbus_queue_processed (test->dbus); g_object_unref (test->dbus); test->dbus = NULL; g_main_loop_unref (test->mainloop); test->mainloop = NULL; g_clear_error (&test->error); tp_clear_object (&test->result); } static void teardown_service (Test *test, gconstpointer data) { tp_dbus_daemon_release_name (test->dbus, TP_ACCOUNT_MANAGER_BUS_NAME, &test->error); g_assert_no_error (test->error); tp_dbus_daemon_unregister_object (test->dbus, test->account_service); g_clear_object (&test->account_service); tp_tests_connection_assert_disconnect_succeeds (test->conn1); g_clear_object (&test->conn1); g_clear_object (&test->conn1_service); tp_tests_connection_assert_disconnect_succeeds (test->conn2); g_clear_object (&test->conn2); g_clear_object (&test->conn2_service); teardown (test, data); } static void test_new (Test *test, gconstpointer data G_GNUC_UNUSED) { test->account = tp_account_new (test->dbus, "/secretly/not/an/object", NULL); g_assert (test->account == NULL); test->account = tp_account_new (test->dbus, "not even syntactically valid", NULL); g_assert (test->account == NULL); test->account = tp_account_new (test->dbus, "/org/freedesktop/Telepathy/Account/what/ev/er", NULL); g_assert (test->account != NULL); } static void test_setters (Test *test, gconstpointer data G_GNUC_UNUSED) { test->account = tp_account_new (test->dbus, "/org/freedesktop/Telepathy/Account/what/ev/er", NULL); g_assert (test->account != NULL); tp_account_set_enabled_async (test->account, TRUE, tp_tests_result_ready_cb, &test->result); tp_tests_run_until_result (&test->result); tp_account_set_enabled_finish (test->account, test->result, &test->error); g_assert_error (test->error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED); g_clear_error (&test->error); tp_clear_object (&test->result); } static void test_reconnect (Test *test, gconstpointer data) { GStrv reconnect_required; const gchar *unset[] = { "unset", NULL }; test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL); g_assert (test->account != NULL); if (!tp_strdiff (data, "vardict")) { tp_account_update_parameters_vardict_async (test->account, g_variant_new_parsed ("{ 'set': <%s> }", "value"), unset, tp_tests_result_ready_cb, &test->result); tp_tests_run_until_result (&test->result); tp_account_update_parameters_vardict_finish (test->account, test->result, &reconnect_required, &test->error); } else { GHashTable *set = tp_asv_new ( "set", G_TYPE_STRING, "value", NULL); tp_account_update_parameters_async (test->account, set, unset, tp_tests_result_ready_cb, &test->result); tp_tests_run_until_result (&test->result); tp_account_update_parameters_finish (test->account, test->result, &reconnect_required, &test->error); g_hash_table_unref (set); } g_assert_no_error (test->error); /* check that reconnect_required survives longer than result */ tp_clear_object (&test->result); g_assert (reconnect_required != NULL); g_assert_cmpstr (reconnect_required[0], ==, "set"); g_assert_cmpstr (reconnect_required[1], ==, "unset"); g_assert_cmpstr (reconnect_required[2], ==, NULL); g_strfreev (reconnect_required); tp_account_reconnect_async (test->account, tp_tests_result_ready_cb, &test->result); tp_tests_run_until_result (&test->result); tp_account_reconnect_finish (test->account, test->result, &test->error); g_assert_error (test->error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED); g_clear_error (&test->error); tp_clear_object (&test->result); } static void account_prepare_cb (GObject *source, GAsyncResult *result, gpointer user_data) { Test *test = user_data; GError *error = NULL; tp_proxy_prepare_finish (source, result, &error); g_assert_no_error (error); g_main_loop_quit (test->mainloop); } #define assert_strprop(self, prop, val) \ {\ gchar *_s; \ \ g_object_get (self, \ prop, &_s, \ NULL); \ g_assert_cmpstr (_s, ==, val);\ g_free (_s); \ } #define assert_uintprop(self, prop, val) \ {\ guint _u; \ \ g_object_get (self, \ prop, &_u, \ NULL); \ g_assert_cmpuint (_u, ==, val);\ } #define assert_boolprop(self, prop, val) \ {\ gboolean _b; \ \ g_object_get (self, \ prop, &_b, \ NULL); \ g_assert_cmpint (_b, ==, val);\ } static void test_prepare_success (Test *test, gconstpointer data G_GNUC_UNUSED) { GQuark account_features[] = { TP_ACCOUNT_FEATURE_CORE, 0 }; TpConnectionStatusReason reason; gchar *status = NULL; gchar *message = NULL; const GHashTable *details = GUINT_TO_POINTER (666); GStrv strv; const gchar * const *cstrv; GVariant *variant; test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL); g_assert (test->account != NULL); tp_proxy_prepare_async (test->account, account_features, account_prepare_cb, test); g_main_loop_run (test->mainloop); /* the obvious accessors */ g_assert (tp_proxy_is_prepared (test->account, TP_ACCOUNT_FEATURE_CORE)); g_assert (tp_account_is_enabled (test->account)); assert_boolprop (test->account, "enabled", TRUE); g_assert (tp_account_is_valid (test->account)); assert_boolprop (test->account, "valid", TRUE); g_assert_cmpstr (tp_account_get_display_name (test->account), ==, "Fake Account"); assert_strprop (test->account, "display-name", "Fake Account"); g_assert_cmpstr (tp_account_get_nickname (test->account), ==, "badger"); assert_strprop (test->account, "nickname", "badger"); g_assert_cmpuint (tp_asv_size (tp_account_get_parameters (test->account)), ==, 0); variant = tp_account_dup_parameters_vardict (test->account); g_assert_cmpstr (g_variant_get_type_string (variant), ==, "a{sv}"); g_assert_cmpuint (g_variant_n_children (variant), ==, 0); g_variant_unref (variant); g_assert (!tp_account_get_connect_automatically (test->account)); assert_boolprop (test->account, "connect-automatically", FALSE); g_assert (tp_account_get_has_been_online (test->account)); assert_boolprop (test->account, "has-been-online", TRUE); g_assert_cmpint (tp_account_get_connection_status (test->account, NULL), ==, TP_CONNECTION_STATUS_CONNECTED); assert_uintprop (test->account, "connection-status", TP_CONNECTION_STATUS_CONNECTED); g_assert_cmpint (tp_account_get_connection_status (test->account, &reason), ==, TP_CONNECTION_STATUS_CONNECTED); g_assert_cmpint (reason, ==, TP_CONNECTION_STATUS_REASON_REQUESTED); assert_uintprop (test->account, "connection-status-reason", TP_CONNECTION_STATUS_REASON_REQUESTED); g_assert_cmpstr (tp_account_get_detailed_error (test->account, NULL), ==, NULL); assert_strprop (test->account, "connection-error", NULL); g_assert_cmpstr (tp_account_get_detailed_error (test->account, &details), ==, NULL); /* this is documented to be untouched */ g_assert_cmpuint (GPOINTER_TO_UINT (details), ==, 666); /* the CM and protocol come from the object path */ g_assert_cmpstr (tp_account_get_cm_name (test->account), ==, "what"); assert_strprop (test->account, "cm-name", "what"); g_assert_cmpstr (tp_account_get_protocol_name (test->account), ==, "ev"); assert_strprop (test->account, "protocol-name", "ev"); /* the icon name in SimpleAccount is "", so we guess based on the protocol */ g_assert_cmpstr (tp_account_get_icon_name (test->account), ==, "im-ev"); assert_strprop (test->account, "icon-name", "im-ev"); /* RequestedPresence */ g_assert_cmpint (tp_account_get_requested_presence (test->account, NULL, NULL), ==, TP_CONNECTION_PRESENCE_TYPE_BUSY); assert_uintprop (test->account, "requested-presence-type", TP_CONNECTION_PRESENCE_TYPE_BUSY); g_assert_cmpint (tp_account_get_requested_presence (test->account, &status, NULL), ==, TP_CONNECTION_PRESENCE_TYPE_BUSY); g_assert_cmpstr (status, ==, "requesting"); g_free (status); assert_strprop (test->account, "requested-status", "requesting"); g_assert_cmpint (tp_account_get_requested_presence (test->account, NULL, &message), ==, TP_CONNECTION_PRESENCE_TYPE_BUSY); g_assert_cmpstr (message, ==, "this is my RequestedPresence"); g_free (message); assert_strprop (test->account, "requested-status-message", "this is my RequestedPresence"); /* CurrentPresence */ g_assert_cmpint (tp_account_get_current_presence (test->account, NULL, NULL), ==, TP_CONNECTION_PRESENCE_TYPE_AWAY); assert_uintprop (test->account, "current-presence-type", TP_CONNECTION_PRESENCE_TYPE_AWAY); g_assert_cmpint (tp_account_get_current_presence (test->account, &status, NULL), ==, TP_CONNECTION_PRESENCE_TYPE_AWAY); g_assert_cmpstr (status, ==, "currently-away"); g_free (status); assert_strprop (test->account, "current-status", "currently-away"); g_assert_cmpint (tp_account_get_current_presence (test->account, NULL, &message), ==, TP_CONNECTION_PRESENCE_TYPE_AWAY); g_assert_cmpstr (message, ==, "this is my CurrentPresence"); g_free (message); assert_strprop (test->account, "current-status-message", "this is my CurrentPresence"); /* AutomaticPresence */ g_assert_cmpint (tp_account_get_automatic_presence (test->account, NULL, NULL), ==, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE); assert_uintprop (test->account, "automatic-presence-type", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE); g_assert_cmpint (tp_account_get_automatic_presence (test->account, &status, NULL), ==, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE); g_assert_cmpstr (status, ==, "automatically-available"); g_free (status); assert_strprop (test->account, "automatic-status", "automatically-available"); g_assert_cmpint (tp_account_get_automatic_presence (test->account, NULL, &message), ==, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE); g_assert_cmpstr (message, ==, "this is my AutomaticPresence"); g_free (message); assert_strprop (test->account, "automatic-status-message", "this is my AutomaticPresence"); /* NormalizedName */ g_assert_cmpstr (tp_account_get_normalized_name (test->account), ==, "bob.mcbadgers@example.com"); assert_strprop (test->account, "normalized-name", "bob.mcbadgers@example.com"); g_object_get (test->account, "supersedes", &strv, NULL); g_assert_cmpstr (strv[0], ==, SUPERSEDED_PATH); g_assert_cmpstr (strv[1], ==, NULL); g_strfreev (strv); cstrv = tp_account_get_supersedes (test->account); g_assert_cmpstr (cstrv[0], ==, SUPERSEDED_PATH); g_assert_cmpstr (cstrv[1], ==, NULL); } static void test_storage (Test *test, gconstpointer mode) { GQuark account_features[] = { TP_ACCOUNT_FEATURE_STORAGE, 0 }; GValue *gvalue; GVariant *gvariant; GHashTable *info; GError *error = NULL; gboolean found; gint32 i; guint32 u; const gchar *s; test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL); g_assert (test->account != NULL); if (g_str_equal (mode, "later")) { /* prepare the core feature first */ tp_proxy_prepare_async (test->account, NULL, account_prepare_cb, test); g_main_loop_run (test->mainloop); /* storage stuff doesn't work yet */ g_assert_cmpstr (tp_account_get_storage_provider (test->account), ==, NULL); assert_strprop (test->account, "storage-provider", NULL); g_assert (tp_account_get_storage_identifier (test->account) == NULL); g_object_get (test->account, "storage-identifier", &gvalue, NULL); g_assert (gvalue == NULL); g_assert (tp_account_get_storage_identifier (test->account) == NULL); g_object_get (test->account, "storage-identifier", &gvariant, NULL); g_assert (gvariant == NULL); g_assert_cmpuint (tp_account_get_storage_restrictions (test->account), ==, 0); assert_uintprop (test->account, "storage-restrictions", 0); } /* prepare the storage feature */ tp_proxy_prepare_async (test->account, account_features, account_prepare_cb, test); g_main_loop_run (test->mainloop); g_assert_cmpstr (tp_account_get_storage_provider (test->account), ==, "org.freedesktop.Telepathy.glib.test"); assert_strprop (test->account, "storage-provider", "org.freedesktop.Telepathy.glib.test"); g_assert_cmpstr ( g_value_get_string (tp_account_get_storage_identifier (test->account)), ==, "unique-identifier"); g_object_get (test->account, "storage-identifier", &gvalue, NULL); g_assert_cmpstr (g_value_get_string (gvalue), ==, "unique-identifier"); g_boxed_free (G_TYPE_VALUE, gvalue); gvariant = tp_account_dup_storage_identifier_variant (test->account); g_assert_cmpstr (g_variant_get_type_string (gvariant), ==, "s"); g_assert_cmpstr (g_variant_get_string (gvariant, NULL), ==, "unique-identifier"); g_variant_unref (gvariant); g_object_get (test->account, "storage-identifier-variant", &gvariant, NULL); g_assert_cmpstr (g_variant_get_type_string (gvariant), ==, "s"); g_assert_cmpstr (g_variant_get_string (gvariant, NULL), ==, "unique-identifier"); g_variant_unref (gvariant); g_assert_cmpuint (tp_account_get_storage_restrictions (test->account), ==, TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_ENABLED | TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PARAMETERS); assert_uintprop (test->account, "storage-restrictions", TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_ENABLED | TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PARAMETERS); /* request the StorageSpecificProperties hash */ tp_account_get_storage_specific_information_async (test->account, tp_tests_result_ready_cb, &test->result); tp_tests_run_until_result (&test->result); info = tp_account_get_storage_specific_information_finish ( test->account, test->result, &error); g_assert_no_error (error); g_assert_cmpuint (g_hash_table_size (info), ==, 3); g_assert_cmpint (tp_asv_get_int32 (info, "one", NULL), ==, 1); g_assert_cmpuint (tp_asv_get_uint32 (info, "two", NULL), ==, 2); g_assert_cmpstr (tp_asv_get_string (info, "marco"), ==, "polo"); tp_clear_object (&test->result); /* the same, but with 100% more GVariant */ tp_account_dup_storage_specific_information_vardict_async (test->account, tp_tests_result_ready_cb, &test->result); tp_tests_run_until_result (&test->result); gvariant = tp_account_dup_storage_specific_information_vardict_finish ( test->account, test->result, &error); g_assert_no_error (error); g_assert_cmpstr (g_variant_get_type_string (gvariant), ==, "a{sv}"); found = g_variant_lookup (gvariant, "one", "i", &i); g_assert (found); g_assert_cmpint (i, ==, 1); found = g_variant_lookup (gvariant, "two", "u", &u); g_assert (found); g_assert_cmpint (u, ==, 2); found = g_variant_lookup (gvariant, "marco", "&s", &s); g_assert (found); g_assert_cmpstr (s, ==, "polo"); found = g_variant_lookup (gvariant, "barisione", "&s", &s); g_assert (!found); g_variant_unref (gvariant); tp_clear_object (&test->result); } static void check_uri_schemes (const gchar * const * schemes) { g_assert (schemes != NULL); g_assert (tp_strv_contains (schemes, "about")); g_assert (tp_strv_contains (schemes, "telnet")); g_assert (schemes[2] == NULL); } static void notify_cb (GObject *object, GParamSpec *spec, Test *test) { g_main_loop_quit (test->mainloop); } static void test_addressing (Test *test, gconstpointer mode) { GQuark account_features[] = { TP_ACCOUNT_FEATURE_ADDRESSING, 0 }; const gchar * const *schemes; GStrv tmp; test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL); g_assert (test->account != NULL); if (g_str_equal (mode, "later")) { /* prepare the core feature first */ tp_proxy_prepare_async (test->account, NULL, account_prepare_cb, test); g_main_loop_run (test->mainloop); /* addressing stuff doesn't work yet */ g_assert (tp_account_get_uri_schemes (test->account) == NULL); g_assert (!tp_account_associated_with_uri_scheme (test->account, "about")); g_assert (!tp_account_associated_with_uri_scheme (test->account, "telnet")); g_assert (!tp_account_associated_with_uri_scheme (test->account, "xmpp")); } /* prepare the addressing feature */ tp_proxy_prepare_async (test->account, account_features, account_prepare_cb, test); g_main_loop_run (test->mainloop); schemes = tp_account_get_uri_schemes (test->account); check_uri_schemes (schemes); g_object_get (test->account, "uri-schemes", &tmp, NULL); check_uri_schemes ((const gchar * const *) tmp); g_strfreev (tmp); g_assert (tp_account_associated_with_uri_scheme (test->account, "about")); g_assert (tp_account_associated_with_uri_scheme (test->account, "telnet")); g_assert (!tp_account_associated_with_uri_scheme (test->account, "xmpp")); g_signal_connect (test->account, "notify::uri-schemes", G_CALLBACK (notify_cb), test); tp_tests_simple_account_add_uri_scheme (test->account_service, "xmpp"); g_main_loop_run (test->mainloop); g_assert (tp_account_associated_with_uri_scheme (test->account, "xmpp")); } static void avatar_changed_cb (TpAccount *account, Test *test) { g_main_loop_quit (test->mainloop); } static void test_avatar (Test *test, gconstpointer mode) { const GArray *blob; GError *error = NULL; test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL); g_assert (test->account != NULL); tp_proxy_prepare_async (test->account, NULL, account_prepare_cb, test); g_main_loop_run (test->mainloop); tp_account_get_avatar_async (test->account, tp_tests_result_ready_cb, &test->result); tp_tests_run_until_result (&test->result); blob = tp_account_get_avatar_finish ( test->account, test->result, &error); g_assert_no_error (error); g_assert_cmpuint (blob->len, ==, 4); g_assert_cmpstr (((char *) blob->data), ==, ":-)"); tp_clear_object (&test->result); /* change the avatar */ g_signal_connect (test->account, "avatar-changed", G_CALLBACK (avatar_changed_cb), test); tp_tests_simple_account_set_avatar (test->account_service, ":-("); g_main_loop_run (test->mainloop); tp_account_get_avatar_async (test->account, tp_tests_result_ready_cb, &test->result); tp_tests_run_until_result (&test->result); blob = tp_account_get_avatar_finish ( test->account, test->result, &error); g_assert_no_error (error); g_assert (blob != NULL); g_assert_cmpuint (blob->len, ==, 4); g_assert_cmpstr (((char *) blob->data), ==, ":-("); tp_clear_object (&test->result); } static void test_connection (Test *test, gconstpointer data G_GNUC_UNUSED) { const gchar *conn1_path = tp_proxy_get_object_path (test->conn1); const gchar *conn2_path = tp_proxy_get_object_path (test->conn2); GQuark account_features[] = { TP_ACCOUNT_FEATURE_CORE, 0 }; GHashTable *change = tp_asv_new (NULL, NULL); TpConnection *conn; const GHashTable *details; GVariant *details_v; gboolean found; gchar *s; guint32 u; test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL); g_assert (test->account != NULL); tp_proxy_prepare_async (test->account, account_features, account_prepare_cb, test); g_main_loop_run (test->mainloop); g_assert (tp_proxy_is_prepared (test->account, TP_ACCOUNT_FEATURE_CORE)); /* a connection turns up */ test_set_up_account_notify (test); tp_asv_set_object_path (change, "Connection", conn1_path); tp_asv_set_uint32 (change, "ConnectionStatus", TP_CONNECTION_STATUS_CONNECTING); tp_asv_set_uint32 (change, "ConnectionStatusReason", TP_CONNECTION_STATUS_REASON_REQUESTED); tp_svc_account_emit_account_property_changed (test->account_service, change); g_hash_table_remove_all (change); while (test_get_times_notified (test, "connection") < 1) g_main_context_iteration (NULL, TRUE); g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1); conn = tp_account_get_connection (test->account); g_assert_cmpstr (tp_proxy_get_object_path (conn), ==, conn1_path); g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1); g_assert_cmpstr (tp_account_get_detailed_error (test->account, NULL), ==, TP_ERROR_STR_CANCELLED); /* ensure the same connection - no change notification */ test_set_up_account_notify (test); conn = tp_account_ensure_connection (test->account, conn1_path); g_assert_cmpstr (tp_proxy_get_object_path (conn), ==, conn1_path); g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 0); /* a no-op "change" */ test_set_up_account_notify (test); tp_asv_set_object_path (change, "Connection", conn1_path); tp_asv_set_uint32 (change, "ConnectionStatus", TP_CONNECTION_STATUS_CONNECTING); tp_asv_set_uint32 (change, "ConnectionStatusReason", TP_CONNECTION_STATUS_REASON_REQUESTED); tp_svc_account_emit_account_property_changed (test->account_service, change); g_hash_table_remove_all (change); tp_tests_proxy_run_until_dbus_queue_processed (test->account); g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 0); conn = tp_account_get_connection (test->account); g_assert_cmpstr (tp_proxy_get_object_path (conn), ==, conn1_path); g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 0); /* atomically flip from one connection to another (unlikely) */ test_set_up_account_notify (test); tp_asv_set_object_path (change, "Connection", conn2_path); tp_asv_set_uint32 (change, "ConnectionStatus", TP_CONNECTION_STATUS_CONNECTED); tp_asv_set_uint32 (change, "ConnectionStatusReason", TP_CONNECTION_STATUS_REASON_REQUESTED); tp_svc_account_emit_account_property_changed (test->account_service, change); g_hash_table_remove_all (change); while (test_get_times_notified (test, "connection") < 1) g_main_context_iteration (NULL, TRUE); g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1); conn = tp_account_get_connection (test->account); g_assert_cmpstr (tp_proxy_get_object_path (conn), ==, conn2_path); g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1); /* no more connection for you */ test_set_up_account_notify (test); tp_asv_set_object_path (change, "Connection", "/"); tp_asv_set_uint32 (change, "ConnectionStatus", TP_CONNECTION_STATUS_DISCONNECTED); tp_asv_set_uint32 (change, "ConnectionStatusReason", TP_CONNECTION_STATUS_REASON_ENCRYPTION_ERROR); tp_svc_account_emit_account_property_changed (test->account_service, change); g_hash_table_remove_all (change); while (test_get_times_notified (test, "connection") < 1) g_main_context_iteration (NULL, TRUE); g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1); conn = tp_account_get_connection (test->account); g_assert (conn == NULL); g_assert_cmpstr (tp_account_get_detailed_error (test->account, NULL), ==, TP_ERROR_STR_ENCRYPTION_ERROR); /* another connection */ test_set_up_account_notify (test); tp_asv_set_object_path (change, "Connection", conn1_path); tp_asv_set_uint32 (change, "ConnectionStatus", TP_CONNECTION_STATUS_CONNECTING); tp_asv_set_uint32 (change, "ConnectionStatusReason", TP_CONNECTION_STATUS_REASON_REQUESTED); tp_svc_account_emit_account_property_changed (test->account_service, change); g_hash_table_remove_all (change); tp_tests_proxy_run_until_dbus_queue_processed (test->account); g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1); /* lose the connection again */ test_set_up_account_notify (test); tp_asv_set_object_path (change, "Connection", "/"); tp_asv_set_uint32 (change, "ConnectionStatus", TP_CONNECTION_STATUS_DISCONNECTED); tp_asv_set_uint32 (change, "ConnectionStatusReason", TP_CONNECTION_STATUS_REASON_ENCRYPTION_ERROR); tp_asv_set_static_string (change, "ConnectionError", "org.debian.packages.OpenSSL.NotRandomEnough"); tp_asv_take_boxed (change, "ConnectionErrorDetails", TP_HASH_TYPE_STRING_VARIANT_MAP, tp_asv_new ( "bits-of-entropy", G_TYPE_UINT, 15, "debug-message", G_TYPE_STRING, "shiiiiii-", NULL)); tp_svc_account_emit_account_property_changed (test->account_service, change); g_hash_table_remove_all (change); tp_tests_proxy_run_until_dbus_queue_processed (test->account); g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1); g_assert_cmpuint (test_get_times_notified (test, "connection-error"), ==, 1); g_assert_cmpstr (tp_account_get_detailed_error (test->account, &details), ==, "org.debian.packages.OpenSSL.NotRandomEnough"); g_assert_cmpuint (tp_asv_size (details), >=, 2); g_assert_cmpstr (tp_asv_get_string (details, "debug-message"), ==, "shiiiiii-"); g_assert_cmpuint (tp_asv_get_uint32 (details, "bits-of-entropy", NULL), ==, 15); s = tp_account_dup_detailed_error_vardict (test->account, &details_v); g_assert_cmpstr (s, ==, "org.debian.packages.OpenSSL.NotRandomEnough"); g_free (s); g_assert_cmpuint (g_variant_n_children (details_v), >=, 2); g_assert_cmpstr (g_variant_get_type_string (details_v), ==, "a{sv}"); found = g_variant_lookup (details_v, "debug-message", "s", &s); g_assert (found); g_assert_cmpstr (s, ==, "shiiiiii-"); g_free (s); found = g_variant_lookup (details_v, "bits-of-entropy", "u", &u); g_assert (found); g_assert_cmpint (u, ==, 15); g_variant_unref (details_v); /* staple on a Connection (this is intended for use in e.g. observers, * if they're told about a Connection that the Account hasn't told them * about yet) */ test_set_up_account_notify (test); conn = tp_account_ensure_connection (test->account, conn1_path); g_assert_cmpstr (tp_proxy_get_object_path (conn), ==, conn1_path); g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1); g_hash_table_unref (change); } int main (int argc, char **argv) { tp_tests_abort_after (10); tp_debug_set_flags ("all"); g_test_init (&argc, &argv, NULL); g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id="); g_test_add_data_func ("/account/parse/spaces", "this is not an object path", test_parse_failure); g_test_add_data_func ("/account/parse/no-prefix", "/this/is/not/an/account/path", test_parse_failure); g_test_add_data_func ("/account/parse/too-few-components", "/org/freedesktop/Telepathy/Account/wrong", test_parse_failure); g_test_add_data_func ("/account/parse/too-many-components", "/org/freedesktop/Telepathy/Account/a/b/c/d", test_parse_failure); g_test_add_data_func ("/account/parse/illegal-components", "/org/freedesktop/Telepathy/Account/1/2/3", test_parse_failure); g_test_add_data_func ("/account/parse/legal", test_parse_data_new ( TP_ACCOUNT_OBJECT_PATH_BASE "gabble/jabber/badgers", "gabble", "jabber", "badgers"), test_parse_success); g_test_add_data_func ("/account/parse/hyphenated-protocol", test_parse_data_new ( TP_ACCOUNT_OBJECT_PATH_BASE "salut/local_xmpp/badgers", "salut", "local-xmpp", "badgers"), test_parse_success); g_test_add_data_func ("/account/parse/wrongly-escaped-protocol", test_parse_data_new ( TP_ACCOUNT_OBJECT_PATH_BASE "salut/local_2dxmpp/badgers", "salut", "local-xmpp", "badgers"), test_parse_success); g_test_add_data_func ("/account/parse/wrongly-escaped-corner-case", test_parse_data_new ( TP_ACCOUNT_OBJECT_PATH_BASE "salut/local_2d/badgers", "salut", "local-", "badgers"), test_parse_success); g_test_add_data_func ("/account/parse/underscored-account", test_parse_data_new ( TP_ACCOUNT_OBJECT_PATH_BASE "haze/msn/_thisseemsunlikely", "haze", "msn", "_thisseemsunlikely"), test_parse_success); g_test_add ("/account/new", Test, NULL, setup, test_new, teardown); g_test_add ("/account/setters", Test, NULL, setup_service, test_setters, teardown_service); g_test_add ("/account/reconnect", Test, NULL, setup_service, test_reconnect, teardown_service); g_test_add ("/account/reconnect", Test, "vardict", setup_service, test_reconnect, teardown_service); g_test_add ("/account/prepare/success", Test, NULL, setup_service, test_prepare_success, teardown_service); g_test_add ("/account/connection", Test, NULL, setup_service, test_connection, teardown_service); g_test_add ("/account/storage", Test, "first", setup_service, test_storage, teardown_service); g_test_add ("/account/storage", Test, "later", setup_service, test_storage, teardown_service); g_test_add ("/account/avatar", Test, NULL, setup_service, test_avatar, teardown_service); g_test_add ("/account/addressing", Test, "first", setup_service, test_addressing, teardown_service); g_test_add ("/account/addressing", Test, "later", setup_service, test_addressing, teardown_service); return tp_tests_run_with_bus (); }