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