1 /* Tests of TpTextChannel
2  *
3  * Copyright © 2010 Collabora Ltd. <http://www.collabora.co.uk/>
4  *
5  * Copying and distribution of this file, with or without modification,
6  * are permitted in any medium without royalty provided the copyright
7  * notice and this notice are preserved.
8  */
9 
10 #include "config.h"
11 
12 #include <string.h>
13 
14 #include <telepathy-glib/telepathy-glib.h>
15 #include <telepathy-glib/message-mixin.h>
16 
17 #include "examples/cm/echo-message-parts/chan.h"
18 
19 #include "tests/lib/contacts-conn.h"
20 #include "tests/lib/util.h"
21 
22 typedef struct {
23     GMainLoop *mainloop;
24     TpDBusDaemon *dbus;
25 
26     /* Service side objects */
27     TpBaseConnection *base_connection;
28     ExampleEcho2Channel *chan_service;
29     ExampleEcho2Channel *sms_chan_service;
30     TpHandleRepoIface *contact_repo;
31     TpHandle bob;
32 
33     /* Client side objects */
34     TpConnection *connection;
35     TpTextChannel *channel;
36     TpTextChannel *sms_channel;
37 
38     TpMessage *received_msg;
39     TpMessage *removed_msg;
40     TpMessage *sent_msg;
41     gchar *token;
42     gchar *sent_token;
43     TpMessageSendingFlags sending_flags;
44 
45     GError *error /* initialized where needed */;
46     gint wait;
47 } Test;
48 
49 static void
create_contact_chan(Test * test)50 create_contact_chan (Test *test)
51 {
52   gchar *chan_path;
53   GHashTable *props;
54 
55   tp_clear_object (&test->chan_service);
56   tp_clear_object (&test->sms_chan_service);
57 
58   /* Create service-side tube channel object */
59   chan_path = g_strdup_printf ("%s/Channel",
60       tp_proxy_get_object_path (test->connection));
61 
62   test->contact_repo = tp_base_connection_get_handles (test->base_connection,
63       TP_HANDLE_TYPE_CONTACT);
64   g_assert (test->contact_repo != NULL);
65 
66   test->bob = tp_handle_ensure (test->contact_repo, "bob", NULL, &test->error);
67   g_assert_no_error (test->error);
68   g_assert (test->bob != 0);
69 
70   test->chan_service = g_object_new (
71       EXAMPLE_TYPE_ECHO_2_CHANNEL,
72       "connection", test->base_connection,
73       "handle", test->bob,
74       "object-path", chan_path,
75       NULL);
76 
77   g_object_get (test->chan_service,
78       "channel-properties", &props,
79       NULL);
80 
81   test->channel = tp_text_channel_new (test->connection, chan_path,
82       props, &test->error);
83   g_assert_no_error (test->error);
84 
85   g_free (chan_path);
86   g_hash_table_unref (props);
87 
88   /* Register channel implementing SMS */
89   chan_path = g_strdup_printf ("%s/ChannelSMS",
90       tp_proxy_get_object_path (test->connection));
91 
92   test->sms_chan_service = g_object_new (
93       EXAMPLE_TYPE_ECHO_2_CHANNEL,
94       "connection", test->base_connection,
95       "handle", test->bob,
96       "object-path", chan_path,
97       "sms", TRUE,
98       NULL);
99 
100   g_object_get (test->chan_service,
101       "channel-properties", &props,
102       NULL);
103 
104   test->sms_channel = tp_text_channel_new (test->connection, chan_path,
105       props, &test->error);
106   g_assert_no_error (test->error);
107 
108   g_free (chan_path);
109   g_hash_table_unref (props);
110 }
111 
112 static void
setup(Test * test,gconstpointer data)113 setup (Test *test,
114        gconstpointer data)
115 {
116   test->mainloop = g_main_loop_new (NULL, FALSE);
117   test->dbus = tp_tests_dbus_daemon_dup_or_die ();
118 
119   test->error = NULL;
120 
121   /* Create (service and client sides) connection objects */
122   tp_tests_create_and_connect_conn (TP_TESTS_TYPE_CONTACTS_CONNECTION,
123       "me@test.com", &test->base_connection, &test->connection);
124 
125   create_contact_chan (test);
126 }
127 
128 static void
teardown(Test * test,gconstpointer data)129 teardown (Test *test,
130           gconstpointer data)
131 {
132   g_clear_error (&test->error);
133 
134   tp_clear_object (&test->dbus);
135   g_main_loop_unref (test->mainloop);
136   test->mainloop = NULL;
137 
138   tp_clear_object (&test->chan_service);
139   tp_clear_object (&test->sms_chan_service);
140 
141   tp_tests_connection_assert_disconnect_succeeds (test->connection);
142   g_object_unref (test->connection);
143   g_object_unref (test->base_connection);
144 
145   tp_clear_object (&test->received_msg);
146   tp_clear_object (&test->removed_msg);
147   tp_clear_object (&test->sent_msg);
148   tp_clear_pointer (&test->token, g_free);
149   tp_clear_pointer (&test->sent_token, g_free);
150 
151   tp_clear_object (&test->channel);
152   tp_clear_object (&test->sms_channel);
153 }
154 
155 static void
test_creation(Test * test,gconstpointer data G_GNUC_UNUSED)156 test_creation (Test *test,
157     gconstpointer data G_GNUC_UNUSED)
158 {
159   const GError *error = NULL;
160 
161   g_assert (TP_IS_TEXT_CHANNEL (test->channel));
162 
163   error = tp_proxy_get_invalidated (test->channel);
164   g_assert_no_error (error);
165 }
166 
167 static void
check_messages_types(GArray * message_types)168 check_messages_types (GArray *message_types)
169 {
170   TpChannelTextMessageType type;
171 
172   g_assert (message_types != NULL);
173   g_assert_cmpuint (message_types->len, ==, 3);
174 
175   type = g_array_index (message_types, TpChannelTextMessageType, 0);
176   g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL);
177   type = g_array_index (message_types, TpChannelTextMessageType, 1);
178   g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION);
179   type = g_array_index (message_types, TpChannelTextMessageType, 2);
180   g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE);
181 }
182 
183 static void
test_properties(Test * test,gconstpointer data G_GNUC_UNUSED)184 test_properties (Test *test,
185     gconstpointer data G_GNUC_UNUSED)
186 {
187   GStrv content_types;
188   const gchar * const * content_types2;
189   TpMessagePartSupportFlags message_part;
190   TpDeliveryReportingSupportFlags delivery;
191   GArray *message_types;
192 
193   g_object_get (test->channel,
194       "supported-content-types", &content_types,
195       "message-part-support-flags", &message_part,
196       "delivery-reporting-support", &delivery,
197       "message-types", &message_types,
198       NULL);
199 
200   /* SupportedContentTypes */
201   g_assert_cmpuint (g_strv_length (content_types), ==, 1);
202   g_assert_cmpstr (content_types[0], ==, "*/*");
203   g_strfreev (content_types);
204 
205   content_types2 = tp_text_channel_get_supported_content_types (test->channel);
206   g_assert_cmpstr (content_types2[0], ==, "*/*");
207 
208   /* MessagePartSupportFlags */
209   g_assert_cmpuint (message_part, ==,
210       TP_MESSAGE_PART_SUPPORT_FLAG_ONE_ATTACHMENT |
211       TP_MESSAGE_PART_SUPPORT_FLAG_MULTIPLE_ATTACHMENTS |
212       TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES);
213   g_assert_cmpuint (message_part, ==,
214       tp_text_channel_get_message_part_support_flags (test->channel));
215 
216   /* DeliveryReportingSupport */
217   g_assert_cmpuint (delivery, ==,
218       TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES);
219   g_assert_cmpuint (delivery, ==,
220       tp_text_channel_get_delivery_reporting_support (test->channel));
221 
222   /* MessageTypes */
223   check_messages_types (message_types);
224   g_array_unref (message_types);
225 
226   message_types = tp_text_channel_get_message_types (test->channel);
227   check_messages_types (message_types);
228 
229   g_assert (tp_text_channel_supports_message_type (test->channel,
230       TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL));
231   g_assert (tp_text_channel_supports_message_type (test->channel,
232       TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION));
233   g_assert (tp_text_channel_supports_message_type (test->channel,
234       TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE));
235   g_assert (!tp_text_channel_supports_message_type (test->channel,
236       TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY));
237   g_assert (!tp_text_channel_supports_message_type (test->channel,
238       TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT));
239 }
240 
241 static void
proxy_prepare_cb(GObject * source,GAsyncResult * result,gpointer user_data)242 proxy_prepare_cb (GObject *source,
243     GAsyncResult *result,
244     gpointer user_data)
245 {
246   Test *test = user_data;
247 
248   tp_proxy_prepare_finish (source, result, &test->error);
249 
250   test->wait--;
251   if (test->wait <= 0)
252     g_main_loop_quit (test->mainloop);
253 }
254 
255 static void
send_message_cb(GObject * source,GAsyncResult * result,gpointer user_data)256 send_message_cb (GObject *source,
257     GAsyncResult *result,
258     gpointer user_data)
259 {
260   Test *test = user_data;
261 
262   tp_clear_pointer (&test->token, g_free);
263 
264   tp_text_channel_send_message_finish (TP_TEXT_CHANNEL (source), result,
265       &test->token, &test->error);
266 
267   test->wait--;
268   if (test->wait <= 0)
269     g_main_loop_quit (test->mainloop);
270 }
271 
272 static void
on_received(TpChannel * chan,guint id,guint timestamp,guint sender,guint type,guint flags,const gchar * text,gpointer user_data,GObject * object)273 on_received (TpChannel *chan,
274     guint id,
275     guint timestamp,
276     guint sender,
277     guint type,
278     guint flags,
279     const gchar *text,
280     gpointer user_data,
281     GObject *object)
282 {
283   Test *test = user_data;
284 
285   test->wait--;
286   if (test->wait <= 0)
287     g_main_loop_quit (test->mainloop);
288 }
289 
290 static void
test_pending_messages(Test * test,gconstpointer data G_GNUC_UNUSED)291 test_pending_messages (Test *test,
292     gconstpointer data G_GNUC_UNUSED)
293 {
294   GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 };
295   GList *messages;
296   TpMessage *msg;
297   gchar *text;
298   TpContact *sender;
299 
300   /* connect on the Received sig to check if the message has been received */
301   tp_cli_channel_type_text_connect_to_received (TP_CHANNEL (test->channel),
302       on_received, test, NULL, NULL, NULL);
303 
304   /* Send a first message */
305   msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
306       "Badger");
307 
308   tp_text_channel_send_message_async (test->channel, msg, 0,
309       send_message_cb, test);
310 
311   g_object_unref (msg);
312 
313   test->wait = 2;
314   g_main_loop_run (test->mainloop);
315   g_assert_no_error (test->error);
316 
317   /* Send a second message */
318   msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
319       "Snake");
320 
321   tp_text_channel_send_message_async (test->channel, msg, 0,
322       send_message_cb, test);
323 
324   g_object_unref (msg);
325 
326   test->wait = 2;
327   g_main_loop_run (test->mainloop);
328   g_assert_no_error (test->error);
329 
330   /* We didn't prepare the feature yet so there is no pending msg */
331   messages = tp_text_channel_get_pending_messages (test->channel);
332   g_assert_cmpuint (g_list_length (messages), ==, 0);
333   g_list_free (messages);
334 
335   tp_proxy_prepare_async (test->channel, features,
336       proxy_prepare_cb, test);
337 
338   g_main_loop_run (test->mainloop);
339   g_assert_no_error (test->error);
340 
341   g_assert (tp_proxy_is_prepared (test->channel,
342         TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES));
343 
344   /* We have the pending messages now */
345   messages = tp_text_channel_get_pending_messages (test->channel);
346   g_assert_cmpuint (g_list_length (messages), ==, 2);
347 
348   /* Check first message */
349   msg = messages->data;
350   g_assert (TP_IS_SIGNALLED_MESSAGE (msg));
351 
352   text = tp_message_to_text (msg, NULL);
353   g_assert_cmpstr (text, ==, "Badger");
354   g_free (text);
355   sender = tp_signalled_message_get_sender (msg);
356   g_assert (sender != NULL);
357   g_assert_cmpstr (tp_contact_get_identifier (sender), ==, "bob");
358 
359   /* Check second message */
360   msg = messages->next->data;
361   g_assert (TP_IS_SIGNALLED_MESSAGE (msg));
362 
363   text = tp_message_to_text (msg, NULL);
364   g_assert_cmpstr (text, ==, "Snake");
365   g_free (text);
366   sender = tp_signalled_message_get_sender (msg);
367   g_assert (sender != NULL);
368   g_assert_cmpstr (tp_contact_get_identifier (sender), ==, "bob");
369 
370   g_list_free (messages);
371 }
372 
373 static void
message_received_cb(TpTextChannel * chan,TpSignalledMessage * msg,Test * test)374 message_received_cb (TpTextChannel *chan,
375     TpSignalledMessage *msg,
376     Test *test)
377 {
378   tp_clear_object (&test->received_msg);
379 
380   test->received_msg = g_object_ref (msg);
381 
382   test->wait--;
383   if (test->wait <= 0)
384     g_main_loop_quit (test->mainloop);
385 }
386 
387 static void
test_message_received(Test * test,gconstpointer data G_GNUC_UNUSED)388 test_message_received (Test *test,
389     gconstpointer data G_GNUC_UNUSED)
390 {
391   GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 };
392   TpMessage *msg;
393   gchar *text;
394   TpContact *sender;
395 
396   /* We have to prepare the pending messages feature to be notified about
397    * incoming messages */
398   tp_proxy_prepare_async (test->channel, features,
399       proxy_prepare_cb, test);
400 
401   g_main_loop_run (test->mainloop);
402   g_assert_no_error (test->error);
403 
404   g_signal_connect (test->channel, "message-received",
405       G_CALLBACK (message_received_cb), test);
406 
407   msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
408       "Snake");
409 
410   tp_text_channel_send_message_async (test->channel, msg, 0,
411       send_message_cb, test);
412 
413   test->wait = 2;
414   g_main_loop_run (test->mainloop);
415   g_assert_no_error (test->error);
416 
417   text = tp_message_to_text (test->received_msg, NULL);
418   g_assert_cmpstr (text, ==, "Snake");
419   g_free (text);
420 
421   sender = tp_signalled_message_get_sender (test->received_msg);
422   g_assert (sender != NULL);
423   g_assert_cmpstr (tp_contact_get_identifier (sender), ==, "bob");
424 
425   g_object_unref (msg);
426 }
427 
428 static void
messages_acked_cb(GObject * source,GAsyncResult * result,gpointer user_data)429 messages_acked_cb (GObject *source,
430     GAsyncResult *result,
431     gpointer user_data)
432 {
433   Test *test = user_data;
434 
435   tp_text_channel_ack_messages_finish (TP_TEXT_CHANNEL (source), result,
436       &test->error);
437 
438   test->wait--;
439   if (test->wait <= 0)
440     g_main_loop_quit (test->mainloop);
441 }
442 
443 static void
test_ack_messages(Test * test,gconstpointer data G_GNUC_UNUSED)444 test_ack_messages (Test *test,
445     gconstpointer data G_GNUC_UNUSED)
446 {
447   GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 };
448   GList *messages;
449   TpMessage *msg;
450 
451   /* Send a first message */
452   msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
453       "Badger");
454 
455   tp_text_channel_send_message_async (test->channel, msg, 0,
456       send_message_cb, test);
457 
458   g_object_unref (msg);
459 
460   /* Send a second message */
461   msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
462       "Snake");
463 
464   tp_text_channel_send_message_async (test->channel, msg, 0,
465       send_message_cb, test);
466 
467   g_object_unref (msg);
468 
469   test->wait = 2;
470   g_main_loop_run (test->mainloop);
471   g_assert_no_error (test->error);
472 
473   tp_proxy_prepare_async (test->channel, features,
474       proxy_prepare_cb, test);
475 
476   g_main_loop_run (test->mainloop);
477   g_assert_no_error (test->error);
478 
479   messages = tp_text_channel_get_pending_messages (test->channel);
480   g_assert_cmpuint (g_list_length (messages), ==, 2);
481 
482   tp_text_channel_ack_messages_async (test->channel, messages,
483       messages_acked_cb, test);
484 
485   g_main_loop_run (test->mainloop);
486   g_assert_no_error (test->error);
487 
488   g_list_free (messages);
489 
490   /* Messages have been acked so there is no pending messages */
491   messages = tp_text_channel_get_pending_messages (test->channel);
492   g_assert_cmpuint (g_list_length (messages), ==, 0);
493 }
494 
495 static void
message_acked_cb(GObject * source,GAsyncResult * result,gpointer user_data)496 message_acked_cb (GObject *source,
497     GAsyncResult *result,
498     gpointer user_data)
499 {
500   Test *test = user_data;
501 
502   tp_text_channel_ack_message_finish (TP_TEXT_CHANNEL (source), result,
503       &test->error);
504 
505   test->wait--;
506   if (test->wait <= 0)
507     g_main_loop_quit (test->mainloop);
508 }
509 
510 static void
pending_message_removed_cb(TpTextChannel * chan,TpSignalledMessage * msg,Test * test)511 pending_message_removed_cb (TpTextChannel *chan,
512     TpSignalledMessage *msg,
513     Test *test)
514 {
515   tp_clear_object (&test->removed_msg);
516 
517   test->removed_msg = g_object_ref (msg);
518 
519   test->wait--;
520   if (test->wait <= 0)
521     g_main_loop_quit (test->mainloop);
522 }
523 
524 static void
test_ack_message(Test * test,gconstpointer data G_GNUC_UNUSED)525 test_ack_message (Test *test,
526     gconstpointer data G_GNUC_UNUSED)
527 {
528   GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 };
529   GList *messages;
530   TpMessage *msg;
531 
532   tp_proxy_prepare_async (test->channel, features,
533       proxy_prepare_cb, test);
534 
535   g_main_loop_run (test->mainloop);
536   g_assert_no_error (test->error);
537 
538   g_signal_connect (test->channel, "message-received",
539       G_CALLBACK (message_received_cb), test);
540 
541   /* Send message */
542   msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
543       "Badger");
544 
545   tp_text_channel_send_message_async (test->channel, msg, 0,
546       send_message_cb, test);
547 
548   g_object_unref (msg);
549 
550   test->wait = 2;
551   g_main_loop_run (test->mainloop);
552   g_assert_no_error (test->error);
553 
554   g_assert (TP_IS_SIGNALLED_MESSAGE (test->received_msg));
555 
556   g_signal_connect (test->channel, "pending-message-removed",
557       G_CALLBACK (pending_message_removed_cb), test);
558 
559   tp_text_channel_ack_message_async (test->channel, test->received_msg,
560       message_acked_cb, test);
561 
562   test->wait = 2;
563   g_main_loop_run (test->mainloop);
564   g_assert_no_error (test->error);
565 
566   g_assert (test->received_msg == test->removed_msg);
567 
568   /* Messages has been acked so there is no pending messages */
569   messages = tp_text_channel_get_pending_messages (test->channel);
570   g_assert_cmpuint (g_list_length (messages), ==, 0);
571 }
572 
573 static void
message_sent_cb(TpTextChannel * channel,TpSignalledMessage * message,TpMessageSendingFlags flags,const gchar * token,Test * test)574 message_sent_cb (TpTextChannel *channel,
575     TpSignalledMessage *message,
576     TpMessageSendingFlags flags,
577     const gchar *token,
578     Test *test)
579 {
580   tp_clear_object (&test->sent_msg);
581   tp_clear_pointer (&test->sent_token, g_free);
582 
583   test->sent_msg = g_object_ref (message);
584   test->sending_flags = flags;
585   if (token != NULL)
586     test->sent_token = g_strdup (token);
587 
588   test->wait--;
589   if (test->wait <= 0)
590     g_main_loop_quit (test->mainloop);
591 }
592 
593 static void
test_message_sent(Test * test,gconstpointer data G_GNUC_UNUSED)594 test_message_sent (Test *test,
595     gconstpointer data G_GNUC_UNUSED)
596 {
597   TpMessage *msg;
598   gchar *text;
599 
600   g_signal_connect (test->channel, "message-sent",
601       G_CALLBACK (message_sent_cb), test);
602 
603   /* Send message */
604   msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
605       "Badger");
606 
607   tp_text_channel_send_message_async (test->channel, msg,
608       TP_MESSAGE_SENDING_FLAG_REPORT_DELIVERY, send_message_cb, test);
609 
610   g_object_unref (msg);
611 
612   test->wait = 2;
613   g_main_loop_run (test->mainloop);
614   g_assert_no_error (test->error);
615 
616   g_assert (TP_IS_SIGNALLED_MESSAGE (test->sent_msg));
617   text = tp_message_to_text (test->sent_msg, NULL);
618   g_assert_cmpstr (text, ==, "Badger");
619   g_free (text);
620 
621   g_assert_cmpuint (test->sending_flags, ==,
622       TP_MESSAGE_SENDING_FLAG_REPORT_DELIVERY);
623   g_assert (test->sent_token == NULL);
624 }
625 
626 static void
notify_cb(GObject * object,GParamSpec * spec,Test * test)627 notify_cb (GObject *object,
628     GParamSpec *spec,
629     Test *test)
630 {
631   test->wait--;
632   if (test->wait <= 0)
633     g_main_loop_quit (test->mainloop);
634 }
635 
636 
637 static void
test_sms_feature(Test * test,gconstpointer data G_GNUC_UNUSED)638 test_sms_feature (Test *test,
639     gconstpointer data G_GNUC_UNUSED)
640 {
641   gboolean is_sms;
642   GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_SMS, 0 };
643 
644   g_assert (tp_text_channel_get_sms_flash (test->sms_channel));
645 
646   /* SMS feature is not prepared yet */
647   g_assert (!tp_text_channel_is_sms_channel (test->sms_channel));
648 
649   g_object_get (test->sms_channel, "is-sms-channel", &is_sms, NULL);
650   g_assert (!is_sms);
651 
652   test->wait++;
653   tp_proxy_prepare_async (test->sms_channel, features,
654       proxy_prepare_cb, test);
655 
656   test->wait++;
657   g_signal_connect (test->sms_channel, "notify::is-sms-channel",
658       G_CALLBACK (notify_cb), test);
659 
660   g_main_loop_run (test->mainloop);
661   g_assert_no_error (test->error);
662 
663   /* Feature has been prepared */
664   g_assert (tp_text_channel_is_sms_channel (test->sms_channel));
665 
666   g_object_get (test->sms_channel, "is-sms-channel", &is_sms, NULL);
667   g_assert (is_sms);
668 
669   /* Property is changed */
670   example_echo_2_channel_set_sms (test->sms_chan_service, FALSE);
671 
672   test->wait++;
673   g_main_loop_run (test->mainloop);
674   g_assert_no_error (test->error);
675 
676   g_assert (!tp_text_channel_is_sms_channel (test->sms_channel));
677 
678   g_object_get (test->sms_channel, "is-sms-channel", &is_sms, NULL);
679   g_assert (!is_sms);
680 }
681 
682 #define MSG "Oh hi!"
683 
684 static void
get_sms_length_cb(GObject * source,GAsyncResult * result,gpointer user_data)685 get_sms_length_cb (GObject *source,
686     GAsyncResult *result,
687     gpointer user_data)
688 {
689   Test *test = user_data;
690   guint chunks_required;
691   gint remaining_characters;
692   gint estimated_cost;
693 
694   tp_text_channel_get_sms_length_finish (TP_TEXT_CHANNEL (source), result,
695       &chunks_required, &remaining_characters, &estimated_cost, &test->error);
696 
697   g_assert_cmpuint (chunks_required, ==, strlen (MSG));
698   g_assert_cmpint (remaining_characters, ==,
699       EXAMPLE_ECHO_2_CHANNEL_MAX_SMS_LENGTH - strlen (MSG));
700   g_assert_cmpint (estimated_cost, ==, -1);
701 
702   test->wait--;
703   if (test->wait <= 0)
704     g_main_loop_quit (test->mainloop);
705 }
706 
707 
708 static void
test_get_sms_length(Test * test,gconstpointer data G_GNUC_UNUSED)709 test_get_sms_length (Test *test,
710     gconstpointer data G_GNUC_UNUSED)
711 {
712   TpMessage *msg;
713 
714   msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, MSG);
715 
716   tp_text_channel_get_sms_length_async (test->channel, msg,
717       get_sms_length_cb, test);
718 
719   test->wait++;
720   g_main_loop_run (test->mainloop);
721   g_assert_no_error (test->error);
722 
723   g_object_unref (msg);
724 }
725 
726 static void
all_pending_messages_acked_cb(GObject * source,GAsyncResult * result,gpointer user_data)727 all_pending_messages_acked_cb (GObject *source,
728     GAsyncResult *result,
729     gpointer user_data)
730 {
731   Test *test = user_data;
732 
733   tp_text_channel_ack_all_pending_messages_finish (TP_TEXT_CHANNEL (source),
734       result, &test->error);
735 
736   test->wait--;
737   if (test->wait <= 0)
738     g_main_loop_quit (test->mainloop);
739 }
740 
741 static void
test_ack_all_pending_messages(Test * test,gconstpointer data G_GNUC_UNUSED)742 test_ack_all_pending_messages (Test *test,
743     gconstpointer data G_GNUC_UNUSED)
744 {
745   GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 };
746   GList *messages;
747   TpMessage *msg;
748 
749   /* Send a first message */
750   msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
751       "Badger");
752 
753   tp_text_channel_send_message_async (test->channel, msg, 0,
754       send_message_cb, test);
755 
756   g_object_unref (msg);
757 
758   /* Send a second message */
759   msg = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
760       "Snake");
761 
762   tp_text_channel_send_message_async (test->channel, msg, 0,
763       send_message_cb, test);
764 
765   g_object_unref (msg);
766 
767   test->wait = 2;
768   g_main_loop_run (test->mainloop);
769   g_assert_no_error (test->error);
770 
771   tp_proxy_prepare_async (test->channel, features,
772       proxy_prepare_cb, test);
773 
774   g_main_loop_run (test->mainloop);
775   g_assert_no_error (test->error);
776 
777   messages = tp_text_channel_get_pending_messages (test->channel);
778   g_assert_cmpuint (g_list_length (messages), ==, 2);
779 
780   tp_text_channel_ack_all_pending_messages_async (test->channel,
781       all_pending_messages_acked_cb, test);
782 
783   g_main_loop_run (test->mainloop);
784   g_assert_no_error (test->error);
785 
786   g_list_free (messages);
787 
788   /* Messages have been acked so there is no pending messages */
789   messages = tp_text_channel_get_pending_messages (test->channel);
790   g_assert_cmpuint (g_list_length (messages), ==, 0);
791 }
792 
793 static void
test_pending_messages_with_no_sender_id(Test * test,gconstpointer data G_GNUC_UNUSED)794 test_pending_messages_with_no_sender_id (Test *test,
795     gconstpointer data G_GNUC_UNUSED)
796 {
797   GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 };
798   TpMessage *cm_message;
799   TpMessage *signalled_message;
800   GList *messages;
801   TpContact *sender;
802   gchar *text;
803 
804   g_test_bug ("39172");
805 
806   /* Deliberately passing sender=0 so we can set message-sender manually; if we set
807    * it here, or using tp_cm_message_set_sender(), message-sender-id will be
808    * filled in, which is exactly what we don't want.
809    */
810   cm_message = tp_cm_message_new_text (test->base_connection, 0,
811       TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, "hi mum");
812   tp_message_set_uint32 (cm_message, 0, "message-sender", test->bob);
813   g_assert_cmpstr (NULL, ==,
814       tp_asv_get_string (tp_message_peek (cm_message, 0), "message-sender-id"));
815   tp_message_mixin_take_received (G_OBJECT (test->chan_service), cm_message);
816 
817   test->wait = 1;
818   tp_proxy_prepare_async (test->channel, features,
819       proxy_prepare_cb, test);
820   g_main_loop_run (test->mainloop);
821   g_assert_no_error (test->error);
822 
823   messages = tp_text_channel_get_pending_messages (test->channel);
824   g_assert (messages != NULL);
825   g_assert_cmpuint (g_list_length (messages), ==, 1);
826 
827   signalled_message = messages->data;
828   sender = tp_signalled_message_get_sender (signalled_message);
829   g_assert (sender != NULL);
830   g_assert_cmpstr (tp_contact_get_identifier (sender), ==, "bob");
831 
832   text = tp_message_to_text ((TpMessage *) signalled_message, NULL);
833   g_assert_cmpstr (text, ==, "hi mum");
834   g_free (text);
835 
836   g_list_free (messages);
837 }
838 
839 static void
test_sender_prepared(Test * test,gconstpointer data G_GNUC_UNUSED)840 test_sender_prepared (Test *test,
841     gconstpointer data G_GNUC_UNUSED)
842 {
843   GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 };
844   TpSimpleClientFactory *factory;
845   TpHandle admin;
846   TpContact *sender;
847   TpMessage *msg;
848 
849   tp_tests_proxy_run_until_prepared (test->channel, features);
850 
851   /* Simulate a message received from a new contact */
852   admin = tp_handle_ensure (test->contact_repo, "admin", NULL, NULL);
853   msg = tp_cm_message_new_text (test->base_connection, admin,
854       TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
855       "Service interuption in 1h");
856   tp_message_mixin_take_received ((GObject *) test->chan_service, msg);
857 
858   g_signal_connect (test->channel, "message-received",
859       G_CALLBACK (message_received_cb), test);
860 
861   g_main_loop_run (test->mainloop);
862   g_assert_no_error (test->error);
863 
864   /* No feature was set on the factory */
865   sender = tp_signalled_message_get_sender (test->received_msg);
866   g_assert (!tp_contact_has_feature (sender, TP_CONTACT_FEATURE_ALIAS));
867 
868   /* Now ask to prepare ALIAS, on next msg it will be prepared */
869   factory = tp_proxy_get_factory (test->connection);
870   tp_simple_client_factory_add_contact_features_varargs (factory,
871       TP_CONTACT_FEATURE_ALIAS,
872       TP_CONTACT_FEATURE_INVALID);
873 
874   msg = tp_cm_message_new_text (test->base_connection, admin,
875       TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
876       "Service interuption in 30min");
877   tp_message_mixin_take_received ((GObject *) test->chan_service, msg);
878 
879   g_signal_connect (test->channel, "message-received",
880       G_CALLBACK (message_received_cb), test);
881 
882   g_main_loop_run (test->mainloop);
883   g_assert_no_error (test->error);
884 
885   sender = tp_signalled_message_get_sender (test->received_msg);
886   g_assert (tp_contact_has_feature (sender, TP_CONTACT_FEATURE_ALIAS));
887 }
888 
889 static void
test_sent_with_no_sender(Test * test,gconstpointer data G_GNUC_UNUSED)890 test_sent_with_no_sender (Test *test,
891     gconstpointer data G_GNUC_UNUSED)
892 {
893   GPtrArray *parts;
894   TpContact *sender;
895 
896   tp_tests_proxy_run_until_prepared (test->channel, NULL);
897 
898   /* Simulate a message sent with no sender, it must fallback to
899    * connection's self-contact. Unfortunately we cannot use the message mixin
900    * because it force setting a sender, and we can't use TpCMMessage to create
901    * parts because it's kept private. So back to old school. */
902   parts = g_ptr_array_new_with_free_func ((GDestroyNotify) g_hash_table_unref);
903   g_ptr_array_add (parts, tp_asv_new (
904       "message-type", G_TYPE_UINT, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
905       NULL));
906   g_ptr_array_add (parts, tp_asv_new (
907       "content-type", G_TYPE_STRING, "text/plain",
908       "content", G_TYPE_STRING, "bla bla bla",
909       NULL));
910 
911   g_signal_connect (test->channel, "message-sent",
912       G_CALLBACK (message_sent_cb), test);
913 
914   tp_svc_channel_interface_messages_emit_message_sent (test->chan_service,
915       parts, 0, "this-is-a-token");
916 
917   g_main_loop_run (test->mainloop);
918   g_assert_no_error (test->error);
919 
920   sender = tp_signalled_message_get_sender (test->sent_msg);
921   g_assert (sender == tp_connection_get_self_contact (test->connection));
922 
923   g_ptr_array_unref (parts);
924 }
925 
926 static void
test_receive_muc_delivery(Test * test,gconstpointer data G_GNUC_UNUSED)927 test_receive_muc_delivery (Test *test,
928     gconstpointer data G_GNUC_UNUSED)
929 {
930   GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, 0 };
931   GPtrArray *parts;
932   GHashTable *header;
933 
934   g_test_bug ("41929 ");
935 
936   /* We have to prepare the pending messages feature to be notified about
937    * incoming messages */
938   tp_proxy_prepare_async (test->channel, features,
939       proxy_prepare_cb, test);
940 
941   g_main_loop_run (test->mainloop);
942   g_assert_no_error (test->error);
943 
944   g_signal_connect (test->channel, "message-received",
945       G_CALLBACK (message_received_cb), test);
946 
947   /* build delivery report */
948   parts = g_ptr_array_new_with_free_func ((GDestroyNotify) g_hash_table_unref);
949   header = tp_asv_new (NULL, NULL);
950   g_ptr_array_add (parts, header);
951 
952   tp_asv_set_uint32 (header, "message-type",
953       TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT);
954   tp_asv_set_uint32 (header, "pending-message-id", 5);
955   tp_asv_set_string (header, "message-token", "message_token");
956   tp_asv_set_string (header, "delivery-token", "delivery_token");
957   tp_asv_set_uint32 (header, "delivery-status", TP_DELIVERY_STATUS_DELIVERED);
958 
959   tp_svc_channel_interface_messages_emit_message_received (test->chan_service,
960       parts);
961 
962   test->wait = 1;
963   g_main_loop_run (test->mainloop);
964   g_assert_no_error (test->error);
965 
966   g_assert_cmpuint (tp_message_get_message_type (test->received_msg), ==,
967       TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT);
968 
969   g_ptr_array_unref (parts);
970 }
971 
972 static void
set_chat_state_cb(GObject * source,GAsyncResult * result,gpointer user_data)973 set_chat_state_cb (GObject *source,
974     GAsyncResult *result,
975     gpointer user_data)
976 {
977   Test *test = user_data;
978 
979   tp_text_channel_set_chat_state_finish (TP_TEXT_CHANNEL (source), result,
980       &test->error);
981 
982   test->wait--;
983   if (test->wait <= 0)
984     g_main_loop_quit (test->mainloop);
985 }
986 
987 static void
contact_chat_state_changed_cb(TpTextChannel * channel,TpContact * contact,TpChannelChatState state,Test * test)988 contact_chat_state_changed_cb (TpTextChannel *channel,
989     TpContact *contact,
990     TpChannelChatState state,
991     Test *test)
992 {
993   test->wait--;
994   if (test->wait <= 0)
995     g_main_loop_quit (test->mainloop);
996 }
997 
998 static void
test_chat_state(Test * test,gconstpointer data G_GNUC_UNUSED)999 test_chat_state (Test *test,
1000     gconstpointer data G_GNUC_UNUSED)
1001 {
1002   GQuark features[] = {
1003       TP_CHANNEL_FEATURE_CONTACTS,
1004       TP_TEXT_CHANNEL_FEATURE_CHAT_STATES,
1005       0 };
1006   TpContact *contact;
1007   TpChannelChatState state;
1008 
1009   /* Set an initial chat state, prepare the channel, and verify target contact
1010    * has that state */
1011   tp_message_mixin_change_chat_state (G_OBJECT (test->chan_service),
1012       test->bob, TP_CHANNEL_CHAT_STATE_COMPOSING);
1013 
1014   tp_tests_proxy_run_until_prepared (test->channel, features);
1015 
1016   contact = tp_channel_get_target_contact ((TpChannel *) test->channel);
1017   state = tp_text_channel_get_chat_state (test->channel, contact);
1018   g_assert_cmpuint (state, ==, TP_CHANNEL_CHAT_STATE_COMPOSING);
1019 
1020   /* Test setting invalid chat state */
1021   tp_text_channel_set_chat_state_async (test->channel, -1,
1022       set_chat_state_cb, test);
1023   g_main_loop_run (test->mainloop);
1024   g_assert_error (test->error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT);
1025   g_clear_error (&test->error);
1026 
1027   tp_text_channel_set_chat_state_async (test->channel,
1028       TP_CHANNEL_CHAT_STATE_GONE, set_chat_state_cb, test);
1029   g_main_loop_run (test->mainloop);
1030   g_assert_error (test->error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT);
1031   g_clear_error (&test->error);
1032 
1033   /* Now set a valid chat state and verify self contact has that state */
1034   tp_text_channel_set_chat_state_async (test->channel,
1035       TP_CHANNEL_CHAT_STATE_COMPOSING, set_chat_state_cb, test);
1036   g_signal_connect (test->channel, "contact-chat-state-changed",
1037       G_CALLBACK (contact_chat_state_changed_cb), test);
1038   test->wait = 2;
1039   g_main_loop_run (test->mainloop);
1040   g_assert_no_error (test->error);
1041 
1042   contact = tp_connection_get_self_contact (test->connection);
1043   state = tp_text_channel_get_chat_state (test->channel, contact);
1044   g_assert_cmpuint (state, ==, TP_CHANNEL_CHAT_STATE_COMPOSING);
1045 }
1046 
1047 int
main(int argc,char ** argv)1048 main (int argc,
1049       char **argv)
1050 {
1051   tp_tests_init (&argc, &argv);
1052   g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
1053 
1054   g_test_add ("/text-channel/creation", Test, NULL, setup,
1055       test_creation, teardown);
1056   g_test_add ("/text-channel/properties", Test, NULL, setup,
1057       test_properties, teardown);
1058   g_test_add ("/text-channel/pending-messages", Test, NULL, setup,
1059       test_pending_messages, teardown);
1060   g_test_add ("/text-channel/message-received", Test, NULL, setup,
1061       test_message_received, teardown);
1062   g_test_add ("/text-channel/ack-messages", Test, NULL, setup,
1063       test_ack_messages, teardown);
1064   g_test_add ("/text-channel/ack-message", Test, NULL, setup,
1065       test_ack_message, teardown);
1066   g_test_add ("/text-channel/message-sent", Test, NULL, setup,
1067       test_message_sent, teardown);
1068   g_test_add ("/text-channel/sms-feature", Test, NULL, setup,
1069       test_sms_feature, teardown);
1070   g_test_add ("/text-channel/get-sms-length", Test, NULL, setup,
1071       test_get_sms_length, teardown);
1072   g_test_add ("/text-channel/ack-all-pending-messages", Test, NULL, setup,
1073       test_ack_all_pending_messages, teardown);
1074   g_test_add ("/text-channel/pending-messages-with-no-sender-id", Test, NULL,
1075       setup, test_pending_messages_with_no_sender_id, teardown);
1076   g_test_add ("/text-channel/sender-prepared", Test, NULL, setup,
1077       test_sender_prepared, teardown);
1078   g_test_add ("/text-channel/sent-with-no-sender", Test, NULL, setup,
1079       test_sent_with_no_sender, teardown);
1080   g_test_add ("/text-channel/receive-muc-delivery", Test, NULL, setup,
1081       test_receive_muc_delivery, teardown);
1082   g_test_add ("/text-channel/chat-state", Test, NULL, setup,
1083       test_chat_state, teardown);
1084 
1085   return tp_tests_run_with_bus ();
1086 }
1087