/* Tests of TpTextChannel * * Copyright © 2010 Collabora Ltd. * * 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 "examples/cm/echo-message-parts/chan.h" #include "tests/lib/contacts-conn.h" #include "tests/lib/util.h" typedef struct { GMainLoop *mainloop; TpDBusDaemon *dbus; /* Service side objects */ TpBaseConnection *base_connection; ExampleEcho2Channel *chan_service; ExampleEcho2Channel *sms_chan_service; TpHandleRepoIface *contact_repo; TpHandle bob; /* Client side objects */ TpConnection *connection; TpTextChannel *channel; TpTextChannel *sms_channel; TpMessage *received_msg; TpMessage *removed_msg; TpMessage *sent_msg; gchar *token; gchar *sent_token; TpMessageSendingFlags sending_flags; GError *error /* initialized where needed */; gint wait; } Test; static void create_contact_chan (Test *test) { gchar *chan_path; GHashTable *props; tp_clear_object (&test->chan_service); tp_clear_object (&test->sms_chan_service); /* Create service-side tube channel object */ chan_path = g_strdup_printf ("%s/Channel", tp_proxy_get_object_path (test->connection)); test->contact_repo = tp_base_connection_get_handles (test->base_connection, TP_HANDLE_TYPE_CONTACT); g_assert (test->contact_repo != NULL); test->bob = tp_handle_ensure (test->contact_repo, "bob", NULL, &test->error); g_assert_no_error (test->error); g_assert (test->bob != 0); test->chan_service = g_object_new ( EXAMPLE_TYPE_ECHO_2_CHANNEL, "connection", test->base_connection, "handle", test->bob, "object-path", chan_path, NULL); g_object_get (test->chan_service, "channel-properties", &props, NULL); test->channel = tp_text_channel_new (test->connection, chan_path, props, &test->error); g_assert_no_error (test->error); g_free (chan_path); g_hash_table_unref (props); /* Register channel implementing SMS */ chan_path = g_strdup_printf ("%s/ChannelSMS", tp_proxy_get_object_path (test->connection)); test->sms_chan_service = g_object_new ( EXAMPLE_TYPE_ECHO_2_CHANNEL, "connection", test->base_connection, "handle", test->bob, "object-path", chan_path, "sms", TRUE, NULL); g_object_get (test->chan_service, "channel-properties", &props, NULL); test->sms_channel = tp_text_channel_new (test->connection, chan_path, props, &test->error); g_assert_no_error (test->error); g_free (chan_path); g_hash_table_unref (props); } static void setup (Test *test, gconstpointer data) { test->mainloop = g_main_loop_new (NULL, FALSE); test->dbus = tp_tests_dbus_daemon_dup_or_die (); test->error = NULL; /* Create (service and client sides) connection objects */ tp_tests_create_and_connect_conn (TP_TESTS_TYPE_CONTACTS_CONNECTION, "me@test.com", &test->base_connection, &test->connection); create_contact_chan (test); } static void teardown (Test *test, gconstpointer data) { g_clear_error (&test->error); tp_clear_object (&test->dbus); g_main_loop_unref (test->mainloop); test->mainloop = NULL; tp_clear_object (&test->chan_service); tp_clear_object (&test->sms_chan_service); tp_tests_connection_assert_disconnect_succeeds (test->connection); g_object_unref (test->connection); g_object_unref (test->base_connection); tp_clear_object (&test->received_msg); tp_clear_object (&test->removed_msg); tp_clear_object (&test->sent_msg); tp_clear_pointer (&test->token, g_free); tp_clear_pointer (&test->sent_token, g_free); tp_clear_object (&test->channel); tp_clear_object (&test->sms_channel); } static void test_creation (Test *test, gconstpointer data G_GNUC_UNUSED) { const GError *error = NULL; g_assert (TP_IS_TEXT_CHANNEL (test->channel)); error = tp_proxy_get_invalidated (test->channel); g_assert_no_error (error); } static void check_messages_types (GArray *message_types) { TpChannelTextMessageType type; g_assert (message_types != NULL); g_assert_cmpuint (message_types->len, ==, 3); type = g_array_index (message_types, TpChannelTextMessageType, 0); g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL); type = g_array_index (message_types, TpChannelTextMessageType, 1); g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION); type = g_array_index (message_types, TpChannelTextMessageType, 2); g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE); } static void test_properties (Test *test, gconstpointer data G_GNUC_UNUSED) { GStrv content_types; const gchar * const * content_types2; TpMessagePartSupportFlags message_part; TpDeliveryReportingSupportFlags delivery; GArray *message_types; g_object_get (test->channel, "supported-content-types", &content_types, "message-part-support-flags", &message_part, "delivery-reporting-support", &delivery, "message-types", &message_types, NULL); /* SupportedContentTypes */ g_assert_cmpuint (g_strv_length (content_types), ==, 1); g_assert_cmpstr (content_types[0], ==, "*/*"); g_strfreev (content_types); content_types2 = tp_text_channel_get_supported_content_types (test->channel); g_assert_cmpstr (content_types2[0], ==, "*/*"); /* MessagePartSupportFlags */ g_assert_cmpuint (message_part, ==, TP_MESSAGE_PART_SUPPORT_FLAG_ONE_ATTACHMENT | TP_MESSAGE_PART_SUPPORT_FLAG_MULTIPLE_ATTACHMENTS | TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES); g_assert_cmpuint (message_part, ==, tp_text_channel_get_message_part_support_flags (test->channel)); /* DeliveryReportingSupport */ g_assert_cmpuint (delivery, ==, TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES); g_assert_cmpuint (delivery, ==, tp_text_channel_get_delivery_reporting_support (test->channel)); /* MessageTypes */ check_messages_types (message_types); g_array_unref (message_types); message_types = tp_text_channel_get_message_types (test->channel); check_messages_types (message_types); g_assert (tp_text_channel_supports_message_type (test->channel, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL)); g_assert (tp_text_channel_supports_message_type (test->channel, TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION)); g_assert (tp_text_channel_supports_message_type (test->channel, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE)); g_assert (!tp_text_channel_supports_message_type (test->channel, TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY)); g_assert (!tp_text_channel_supports_message_type (test->channel, TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT)); } static void proxy_prepare_cb (GObject *source, GAsyncResult *result, gpointer user_data) { Test *test = user_data; tp_proxy_prepare_finish (source, result, &test->error); test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void send_message_cb (GObject *source, GAsyncResult *result, gpointer user_data) { Test *test = user_data; tp_clear_pointer (&test->token, g_free); tp_text_channel_send_message_finish (TP_TEXT_CHANNEL (source), result, &test->token, &test->error); test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void on_received (TpChannel *chan, guint id, guint timestamp, guint sender, guint type, guint flags, const gchar *text, gpointer user_data, GObject *object) { Test *test = user_data; test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void test_pending_messages (Test *test, gconstpointer data G_GNUC_UNUSED) { GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 }; GList *messages; TpMessage *msg; gchar *text; TpContact *sender; /* connect on the Received sig to check if the message has been received */ tp_cli_channel_type_text_connect_to_received (TP_CHANNEL (test->channel), on_received, test, NULL, NULL, NULL); /* Send a first message */ msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "Badger"); tp_text_channel_send_message_async (test->channel, msg, 0, send_message_cb, test); g_object_unref (msg); test->wait = 2; g_main_loop_run (test->mainloop); g_assert_no_error (test->error); /* Send a second message */ msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "Snake"); tp_text_channel_send_message_async (test->channel, msg, 0, send_message_cb, test); g_object_unref (msg); test->wait = 2; g_main_loop_run (test->mainloop); g_assert_no_error (test->error); /* We didn't prepare the feature yet so there is no pending msg */ messages = tp_text_channel_get_pending_messages (test->channel); g_assert_cmpuint (g_list_length (messages), ==, 0); g_list_free (messages); tp_proxy_prepare_async (test->channel, features, proxy_prepare_cb, test); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); g_assert (tp_proxy_is_prepared (test->channel, TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES)); /* We have the pending messages now */ messages = tp_text_channel_get_pending_messages (test->channel); g_assert_cmpuint (g_list_length (messages), ==, 2); /* Check first message */ msg = messages->data; g_assert (TP_IS_SIGNALLED_MESSAGE (msg)); text = tp_message_to_text (msg, NULL); g_assert_cmpstr (text, ==, "Badger"); g_free (text); sender = tp_signalled_message_get_sender (msg); g_assert (sender != NULL); g_assert_cmpstr (tp_contact_get_identifier (sender), ==, "bob"); /* Check second message */ msg = messages->next->data; g_assert (TP_IS_SIGNALLED_MESSAGE (msg)); text = tp_message_to_text (msg, NULL); g_assert_cmpstr (text, ==, "Snake"); g_free (text); sender = tp_signalled_message_get_sender (msg); g_assert (sender != NULL); g_assert_cmpstr (tp_contact_get_identifier (sender), ==, "bob"); g_list_free (messages); } static void message_received_cb (TpTextChannel *chan, TpSignalledMessage *msg, Test *test) { tp_clear_object (&test->received_msg); test->received_msg = g_object_ref (msg); test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void test_message_received (Test *test, gconstpointer data G_GNUC_UNUSED) { GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 }; TpMessage *msg; gchar *text; TpContact *sender; /* We have to prepare the pending messages feature to be notified about * incoming messages */ tp_proxy_prepare_async (test->channel, features, proxy_prepare_cb, test); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); g_signal_connect (test->channel, "message-received", G_CALLBACK (message_received_cb), test); msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "Snake"); tp_text_channel_send_message_async (test->channel, msg, 0, send_message_cb, test); test->wait = 2; g_main_loop_run (test->mainloop); g_assert_no_error (test->error); text = tp_message_to_text (test->received_msg, NULL); g_assert_cmpstr (text, ==, "Snake"); g_free (text); sender = tp_signalled_message_get_sender (test->received_msg); g_assert (sender != NULL); g_assert_cmpstr (tp_contact_get_identifier (sender), ==, "bob"); g_object_unref (msg); } static void messages_acked_cb (GObject *source, GAsyncResult *result, gpointer user_data) { Test *test = user_data; tp_text_channel_ack_messages_finish (TP_TEXT_CHANNEL (source), result, &test->error); test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void test_ack_messages (Test *test, gconstpointer data G_GNUC_UNUSED) { GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 }; GList *messages; TpMessage *msg; /* Send a first message */ msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "Badger"); tp_text_channel_send_message_async (test->channel, msg, 0, send_message_cb, test); g_object_unref (msg); /* Send a second message */ msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "Snake"); tp_text_channel_send_message_async (test->channel, msg, 0, send_message_cb, test); g_object_unref (msg); test->wait = 2; g_main_loop_run (test->mainloop); g_assert_no_error (test->error); tp_proxy_prepare_async (test->channel, features, proxy_prepare_cb, test); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); messages = tp_text_channel_get_pending_messages (test->channel); g_assert_cmpuint (g_list_length (messages), ==, 2); tp_text_channel_ack_messages_async (test->channel, messages, messages_acked_cb, test); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); g_list_free (messages); /* Messages have been acked so there is no pending messages */ messages = tp_text_channel_get_pending_messages (test->channel); g_assert_cmpuint (g_list_length (messages), ==, 0); } static void message_acked_cb (GObject *source, GAsyncResult *result, gpointer user_data) { Test *test = user_data; tp_text_channel_ack_message_finish (TP_TEXT_CHANNEL (source), result, &test->error); test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void pending_message_removed_cb (TpTextChannel *chan, TpSignalledMessage *msg, Test *test) { tp_clear_object (&test->removed_msg); test->removed_msg = g_object_ref (msg); test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void test_ack_message (Test *test, gconstpointer data G_GNUC_UNUSED) { GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 }; GList *messages; TpMessage *msg; tp_proxy_prepare_async (test->channel, features, proxy_prepare_cb, test); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); g_signal_connect (test->channel, "message-received", G_CALLBACK (message_received_cb), test); /* Send message */ msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "Badger"); tp_text_channel_send_message_async (test->channel, msg, 0, send_message_cb, test); g_object_unref (msg); test->wait = 2; g_main_loop_run (test->mainloop); g_assert_no_error (test->error); g_assert (TP_IS_SIGNALLED_MESSAGE (test->received_msg)); g_signal_connect (test->channel, "pending-message-removed", G_CALLBACK (pending_message_removed_cb), test); tp_text_channel_ack_message_async (test->channel, test->received_msg, message_acked_cb, test); test->wait = 2; g_main_loop_run (test->mainloop); g_assert_no_error (test->error); g_assert (test->received_msg == test->removed_msg); /* Messages has been acked so there is no pending messages */ messages = tp_text_channel_get_pending_messages (test->channel); g_assert_cmpuint (g_list_length (messages), ==, 0); } static void message_sent_cb (TpTextChannel *channel, TpSignalledMessage *message, TpMessageSendingFlags flags, const gchar *token, Test *test) { tp_clear_object (&test->sent_msg); tp_clear_pointer (&test->sent_token, g_free); test->sent_msg = g_object_ref (message); test->sending_flags = flags; if (token != NULL) test->sent_token = g_strdup (token); test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void test_message_sent (Test *test, gconstpointer data G_GNUC_UNUSED) { TpMessage *msg; gchar *text; g_signal_connect (test->channel, "message-sent", G_CALLBACK (message_sent_cb), test); /* Send message */ msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "Badger"); tp_text_channel_send_message_async (test->channel, msg, TP_MESSAGE_SENDING_FLAG_REPORT_DELIVERY, send_message_cb, test); g_object_unref (msg); test->wait = 2; g_main_loop_run (test->mainloop); g_assert_no_error (test->error); g_assert (TP_IS_SIGNALLED_MESSAGE (test->sent_msg)); text = tp_message_to_text (test->sent_msg, NULL); g_assert_cmpstr (text, ==, "Badger"); g_free (text); g_assert_cmpuint (test->sending_flags, ==, TP_MESSAGE_SENDING_FLAG_REPORT_DELIVERY); g_assert (test->sent_token == NULL); } static void notify_cb (GObject *object, GParamSpec *spec, Test *test) { test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void test_sms_feature (Test *test, gconstpointer data G_GNUC_UNUSED) { gboolean is_sms; GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_SMS, 0 }; g_assert (tp_text_channel_get_sms_flash (test->sms_channel)); /* SMS feature is not prepared yet */ g_assert (!tp_text_channel_is_sms_channel (test->sms_channel)); g_object_get (test->sms_channel, "is-sms-channel", &is_sms, NULL); g_assert (!is_sms); test->wait++; tp_proxy_prepare_async (test->sms_channel, features, proxy_prepare_cb, test); test->wait++; g_signal_connect (test->sms_channel, "notify::is-sms-channel", G_CALLBACK (notify_cb), test); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); /* Feature has been prepared */ g_assert (tp_text_channel_is_sms_channel (test->sms_channel)); g_object_get (test->sms_channel, "is-sms-channel", &is_sms, NULL); g_assert (is_sms); /* Property is changed */ example_echo_2_channel_set_sms (test->sms_chan_service, FALSE); test->wait++; g_main_loop_run (test->mainloop); g_assert_no_error (test->error); g_assert (!tp_text_channel_is_sms_channel (test->sms_channel)); g_object_get (test->sms_channel, "is-sms-channel", &is_sms, NULL); g_assert (!is_sms); } #define MSG "Oh hi!" static void get_sms_length_cb (GObject *source, GAsyncResult *result, gpointer user_data) { Test *test = user_data; guint chunks_required; gint remaining_characters; gint estimated_cost; tp_text_channel_get_sms_length_finish (TP_TEXT_CHANNEL (source), result, &chunks_required, &remaining_characters, &estimated_cost, &test->error); g_assert_cmpuint (chunks_required, ==, strlen (MSG)); g_assert_cmpint (remaining_characters, ==, EXAMPLE_ECHO_2_CHANNEL_MAX_SMS_LENGTH - strlen (MSG)); g_assert_cmpint (estimated_cost, ==, -1); test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void test_get_sms_length (Test *test, gconstpointer data G_GNUC_UNUSED) { TpMessage *msg; msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, MSG); tp_text_channel_get_sms_length_async (test->channel, msg, get_sms_length_cb, test); test->wait++; g_main_loop_run (test->mainloop); g_assert_no_error (test->error); g_object_unref (msg); } static void all_pending_messages_acked_cb (GObject *source, GAsyncResult *result, gpointer user_data) { Test *test = user_data; tp_text_channel_ack_all_pending_messages_finish (TP_TEXT_CHANNEL (source), result, &test->error); test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void test_ack_all_pending_messages (Test *test, gconstpointer data G_GNUC_UNUSED) { GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 }; GList *messages; TpMessage *msg; /* Send a first message */ msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "Badger"); tp_text_channel_send_message_async (test->channel, msg, 0, send_message_cb, test); g_object_unref (msg); /* Send a second message */ msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "Snake"); tp_text_channel_send_message_async (test->channel, msg, 0, send_message_cb, test); g_object_unref (msg); test->wait = 2; g_main_loop_run (test->mainloop); g_assert_no_error (test->error); tp_proxy_prepare_async (test->channel, features, proxy_prepare_cb, test); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); messages = tp_text_channel_get_pending_messages (test->channel); g_assert_cmpuint (g_list_length (messages), ==, 2); tp_text_channel_ack_all_pending_messages_async (test->channel, all_pending_messages_acked_cb, test); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); g_list_free (messages); /* Messages have been acked so there is no pending messages */ messages = tp_text_channel_get_pending_messages (test->channel); g_assert_cmpuint (g_list_length (messages), ==, 0); } static void test_pending_messages_with_no_sender_id (Test *test, gconstpointer data G_GNUC_UNUSED) { GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 }; TpMessage *cm_message; TpMessage *signalled_message; GList *messages; TpContact *sender; gchar *text; g_test_bug ("39172"); /* Deliberately passing sender=0 so we can set message-sender manually; if we set * it here, or using tp_cm_message_set_sender(), message-sender-id will be * filled in, which is exactly what we don't want. */ cm_message = tp_cm_message_new_text (test->base_connection, 0, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "hi mum"); tp_message_set_uint32 (cm_message, 0, "message-sender", test->bob); g_assert_cmpstr (NULL, ==, tp_asv_get_string (tp_message_peek (cm_message, 0), "message-sender-id")); tp_message_mixin_take_received (G_OBJECT (test->chan_service), cm_message); test->wait = 1; tp_proxy_prepare_async (test->channel, features, proxy_prepare_cb, test); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); messages = tp_text_channel_get_pending_messages (test->channel); g_assert (messages != NULL); g_assert_cmpuint (g_list_length (messages), ==, 1); signalled_message = messages->data; sender = tp_signalled_message_get_sender (signalled_message); g_assert (sender != NULL); g_assert_cmpstr (tp_contact_get_identifier (sender), ==, "bob"); text = tp_message_to_text ((TpMessage *) signalled_message, NULL); g_assert_cmpstr (text, ==, "hi mum"); g_free (text); g_list_free (messages); } static void test_sender_prepared (Test *test, gconstpointer data G_GNUC_UNUSED) { GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 }; TpSimpleClientFactory *factory; TpHandle admin; TpContact *sender; TpMessage *msg; tp_tests_proxy_run_until_prepared (test->channel, features); /* Simulate a message received from a new contact */ admin = tp_handle_ensure (test->contact_repo, "admin", NULL, NULL); msg = tp_cm_message_new_text (test->base_connection, admin, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "Service interuption in 1h"); tp_message_mixin_take_received ((GObject *) test->chan_service, msg); g_signal_connect (test->channel, "message-received", G_CALLBACK (message_received_cb), test); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); /* No feature was set on the factory */ sender = tp_signalled_message_get_sender (test->received_msg); g_assert (!tp_contact_has_feature (sender, TP_CONTACT_FEATURE_ALIAS)); /* Now ask to prepare ALIAS, on next msg it will be prepared */ factory = tp_proxy_get_factory (test->connection); tp_simple_client_factory_add_contact_features_varargs (factory, TP_CONTACT_FEATURE_ALIAS, TP_CONTACT_FEATURE_INVALID); msg = tp_cm_message_new_text (test->base_connection, admin, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "Service interuption in 30min"); tp_message_mixin_take_received ((GObject *) test->chan_service, msg); g_signal_connect (test->channel, "message-received", G_CALLBACK (message_received_cb), test); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); sender = tp_signalled_message_get_sender (test->received_msg); g_assert (tp_contact_has_feature (sender, TP_CONTACT_FEATURE_ALIAS)); } static void test_sent_with_no_sender (Test *test, gconstpointer data G_GNUC_UNUSED) { GPtrArray *parts; TpContact *sender; tp_tests_proxy_run_until_prepared (test->channel, NULL); /* Simulate a message sent with no sender, it must fallback to * connection's self-contact. Unfortunately we cannot use the message mixin * because it force setting a sender, and we can't use TpCMMessage to create * parts because it's kept private. So back to old school. */ parts = g_ptr_array_new_with_free_func ((GDestroyNotify) g_hash_table_unref); g_ptr_array_add (parts, tp_asv_new ( "message-type", G_TYPE_UINT, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, NULL)); g_ptr_array_add (parts, tp_asv_new ( "content-type", G_TYPE_STRING, "text/plain", "content", G_TYPE_STRING, "bla bla bla", NULL)); g_signal_connect (test->channel, "message-sent", G_CALLBACK (message_sent_cb), test); tp_svc_channel_interface_messages_emit_message_sent (test->chan_service, parts, 0, "this-is-a-token"); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); sender = tp_signalled_message_get_sender (test->sent_msg); g_assert (sender == tp_connection_get_self_contact (test->connection)); g_ptr_array_unref (parts); } static void test_receive_muc_delivery (Test *test, gconstpointer data G_GNUC_UNUSED) { GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 }; GPtrArray *parts; GHashTable *header; g_test_bug ("41929 "); /* We have to prepare the pending messages feature to be notified about * incoming messages */ tp_proxy_prepare_async (test->channel, features, proxy_prepare_cb, test); g_main_loop_run (test->mainloop); g_assert_no_error (test->error); g_signal_connect (test->channel, "message-received", G_CALLBACK (message_received_cb), test); /* build delivery report */ parts = g_ptr_array_new_with_free_func ((GDestroyNotify) g_hash_table_unref); header = tp_asv_new (NULL, NULL); g_ptr_array_add (parts, header); tp_asv_set_uint32 (header, "message-type", TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT); tp_asv_set_uint32 (header, "pending-message-id", 5); tp_asv_set_string (header, "message-token", "message_token"); tp_asv_set_string (header, "delivery-token", "delivery_token"); tp_asv_set_uint32 (header, "delivery-status", TP_DELIVERY_STATUS_DELIVERED); tp_svc_channel_interface_messages_emit_message_received (test->chan_service, parts); test->wait = 1; g_main_loop_run (test->mainloop); g_assert_no_error (test->error); g_assert_cmpuint (tp_message_get_message_type (test->received_msg), ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT); g_ptr_array_unref (parts); } static void set_chat_state_cb (GObject *source, GAsyncResult *result, gpointer user_data) { Test *test = user_data; tp_text_channel_set_chat_state_finish (TP_TEXT_CHANNEL (source), result, &test->error); test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void contact_chat_state_changed_cb (TpTextChannel *channel, TpContact *contact, TpChannelChatState state, Test *test) { test->wait--; if (test->wait <= 0) g_main_loop_quit (test->mainloop); } static void test_chat_state (Test *test, gconstpointer data G_GNUC_UNUSED) { GQuark features[] = { TP_CHANNEL_FEATURE_CONTACTS, TP_TEXT_CHANNEL_FEATURE_CHAT_STATES, 0 }; TpContact *contact; TpChannelChatState state; /* Set an initial chat state, prepare the channel, and verify target contact * has that state */ tp_message_mixin_change_chat_state (G_OBJECT (test->chan_service), test->bob, TP_CHANNEL_CHAT_STATE_COMPOSING); tp_tests_proxy_run_until_prepared (test->channel, features); contact = tp_channel_get_target_contact ((TpChannel *) test->channel); state = tp_text_channel_get_chat_state (test->channel, contact); g_assert_cmpuint (state, ==, TP_CHANNEL_CHAT_STATE_COMPOSING); /* Test setting invalid chat state */ tp_text_channel_set_chat_state_async (test->channel, -1, set_chat_state_cb, test); g_main_loop_run (test->mainloop); g_assert_error (test->error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT); g_clear_error (&test->error); tp_text_channel_set_chat_state_async (test->channel, TP_CHANNEL_CHAT_STATE_GONE, set_chat_state_cb, test); g_main_loop_run (test->mainloop); g_assert_error (test->error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT); g_clear_error (&test->error); /* Now set a valid chat state and verify self contact has that state */ tp_text_channel_set_chat_state_async (test->channel, TP_CHANNEL_CHAT_STATE_COMPOSING, set_chat_state_cb, test); g_signal_connect (test->channel, "contact-chat-state-changed", G_CALLBACK (contact_chat_state_changed_cb), test); test->wait = 2; g_main_loop_run (test->mainloop); g_assert_no_error (test->error); contact = tp_connection_get_self_contact (test->connection); state = tp_text_channel_get_chat_state (test->channel, contact); g_assert_cmpuint (state, ==, TP_CHANNEL_CHAT_STATE_COMPOSING); } int main (int argc, char **argv) { tp_tests_init (&argc, &argv); g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id="); g_test_add ("/text-channel/creation", Test, NULL, setup, test_creation, teardown); g_test_add ("/text-channel/properties", Test, NULL, setup, test_properties, teardown); g_test_add ("/text-channel/pending-messages", Test, NULL, setup, test_pending_messages, teardown); g_test_add ("/text-channel/message-received", Test, NULL, setup, test_message_received, teardown); g_test_add ("/text-channel/ack-messages", Test, NULL, setup, test_ack_messages, teardown); g_test_add ("/text-channel/ack-message", Test, NULL, setup, test_ack_message, teardown); g_test_add ("/text-channel/message-sent", Test, NULL, setup, test_message_sent, teardown); g_test_add ("/text-channel/sms-feature", Test, NULL, setup, test_sms_feature, teardown); g_test_add ("/text-channel/get-sms-length", Test, NULL, setup, test_get_sms_length, teardown); g_test_add ("/text-channel/ack-all-pending-messages", Test, NULL, setup, test_ack_all_pending_messages, teardown); g_test_add ("/text-channel/pending-messages-with-no-sender-id", Test, NULL, setup, test_pending_messages_with_no_sender_id, teardown); g_test_add ("/text-channel/sender-prepared", Test, NULL, setup, test_sender_prepared, teardown); g_test_add ("/text-channel/sent-with-no-sender", Test, NULL, setup, test_sent_with_no_sender, teardown); g_test_add ("/text-channel/receive-muc-delivery", Test, NULL, setup, test_receive_muc_delivery, teardown); g_test_add ("/text-channel/chat-state", Test, NULL, setup, test_chat_state, teardown); return tp_tests_run_with_bus (); }