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/contactlist/conn.h"
18
19 #include "tests/lib/util.h"
20
21 typedef struct {
22 GMainLoop *mainloop;
23 TpDBusDaemon *dbus;
24
25 /* Service side objects */
26 TpBaseConnection *base_connection;
27 TpHandleRepoIface *contact_repo;
28
29 /* Client side objects */
30 TpConnection *connection;
31 TpTextChannel *channel;
32 TpTextChannel *sms_channel;
33
34 GPtrArray *blocked_added;
35 GPtrArray *blocked_removed;
36 TpContact *contact;
37
38 GError *error /* initialized where needed */;
39 gint wait;
40 } Test;
41
42 static void
setup(Test * test,gconstpointer data)43 setup (Test *test,
44 gconstpointer data)
45 {
46 gchar *conn_name, *conn_path;
47 GQuark conn_features[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 };
48
49 test->mainloop = g_main_loop_new (NULL, FALSE);
50 test->dbus = tp_tests_dbus_daemon_dup_or_die ();
51
52 test->error = NULL;
53
54 /* Create (service and client sides) connection objects */
55 test->base_connection = tp_tests_object_new_static_class (
56 EXAMPLE_TYPE_CONTACT_LIST_CONNECTION,
57 "account", "me@test.com",
58 "simulation-delay", 0,
59 "protocol", "test",
60 NULL);
61
62 g_assert (tp_base_connection_register (test->base_connection, "example",
63 &conn_name, &conn_path, &test->error));
64 g_assert_no_error (test->error);
65
66 test->connection = tp_connection_new (test->dbus, conn_name, conn_path,
67 &test->error);
68 g_assert_no_error (test->error);
69
70 test->contact_repo = tp_base_connection_get_handles (test->base_connection,
71 TP_HANDLE_TYPE_CONTACT);
72 g_assert (test->contact_repo != NULL);
73
74 /* Connect the connection */
75 tp_cli_connection_call_connect (test->connection, -1, NULL, NULL, NULL, NULL);
76 tp_tests_proxy_run_until_prepared (test->connection, conn_features);
77
78 g_free (conn_name);
79 g_free (conn_path);
80 }
81
82 static void
teardown(Test * test,gconstpointer data)83 teardown (Test *test,
84 gconstpointer data)
85 {
86 g_clear_error (&test->error);
87
88 tp_clear_object (&test->dbus);
89 g_main_loop_unref (test->mainloop);
90 test->mainloop = NULL;
91
92 tp_tests_connection_assert_disconnect_succeeds (test->connection);
93 g_object_unref (test->connection);
94 g_object_unref (test->base_connection);
95
96 tp_clear_pointer (&test->blocked_added, g_ptr_array_unref);
97 tp_clear_pointer (&test->blocked_removed, g_ptr_array_unref);
98 g_clear_object (&test->contact);
99 }
100
101 static void
block_contacts_cb(GObject * source,GAsyncResult * result,gpointer user_data)102 block_contacts_cb (GObject *source,
103 GAsyncResult *result,
104 gpointer user_data)
105 {
106 Test *test = user_data;
107
108 tp_connection_block_contacts_finish (TP_CONNECTION (source), result,
109 &test->error);
110 g_assert_no_error (test->error);
111
112 test->wait--;
113 if (test->wait <= 0)
114 g_main_loop_quit (test->mainloop);
115 }
116
117 static void
unblock_contacts_cb(GObject * source,GAsyncResult * result,gpointer user_data)118 unblock_contacts_cb (GObject *source,
119 GAsyncResult *result,
120 gpointer user_data)
121 {
122 Test *test = user_data;
123
124 tp_connection_unblock_contacts_finish (TP_CONNECTION (source), result,
125 &test->error);
126 g_assert_no_error (test->error);
127
128 test->wait--;
129 if (test->wait <= 0)
130 g_main_loop_quit (test->mainloop);
131 }
132
133 static void
contact_block_cb(GObject * source,GAsyncResult * result,gpointer user_data)134 contact_block_cb (GObject *source,
135 GAsyncResult *result,
136 gpointer user_data)
137 {
138 Test *test = user_data;
139
140 tp_contact_block_finish (TP_CONTACT (source), result, &test->error);
141 g_assert_no_error (test->error);
142
143 test->wait--;
144 if (test->wait <= 0)
145 g_main_loop_quit (test->mainloop);
146 }
147
148 static void
contact_unblock_cb(GObject * source,GAsyncResult * result,gpointer user_data)149 contact_unblock_cb (GObject *source,
150 GAsyncResult *result,
151 gpointer user_data)
152 {
153 Test *test = user_data;
154
155 tp_contact_unblock_finish (TP_CONTACT (source), result, &test->error);
156 g_assert_no_error (test->error);
157
158 test->wait--;
159 if (test->wait <= 0)
160 g_main_loop_quit (test->mainloop);
161 }
162
163 static TpContact *
create_contact(Test * test,const gchar * id)164 create_contact (Test *test,
165 const gchar *id)
166 {
167 TpHandle handle;
168 TpContact *contact;
169
170 handle = tp_handle_ensure (test->contact_repo, id, NULL, &test->error);
171 g_assert_no_error (test->error);
172
173 contact = tp_connection_dup_contact_if_possible (test->connection, handle,
174 id);
175 g_assert (contact != NULL);
176
177 return contact;
178 }
179
180 static void
test_block_unblock(Test * test,gconstpointer data G_GNUC_UNUSED)181 test_block_unblock (Test *test,
182 gconstpointer data G_GNUC_UNUSED)
183 {
184 TpContact *alice, *bob;
185 GPtrArray *arr;
186
187 alice = create_contact (test, "alice");
188 bob = create_contact (test, "bob");
189
190 arr = g_ptr_array_sized_new (2);
191 g_ptr_array_add (arr, alice);
192 g_ptr_array_add (arr, bob);
193
194 /* Block contacts */
195 tp_connection_block_contacts_async (test->connection,
196 arr->len, (TpContact * const *) arr->pdata, FALSE,
197 block_contacts_cb, test);
198
199 test->wait = 1;
200 g_main_loop_run (test->mainloop);
201 g_assert_no_error (test->error);
202
203 /* Unblock contacts */
204 tp_connection_unblock_contacts_async (test->connection,
205 arr->len, (TpContact * const *) arr->pdata,
206 unblock_contacts_cb, test);
207
208 test->wait = 1;
209 g_main_loop_run (test->mainloop);
210 g_assert_no_error (test->error);
211
212 g_object_unref (alice);
213 g_object_unref (bob);
214 g_ptr_array_unref (arr);
215 }
216
217 static void
proxy_prepare_cb(GObject * source,GAsyncResult * result,gpointer user_data)218 proxy_prepare_cb (GObject *source,
219 GAsyncResult *result,
220 gpointer user_data)
221 {
222 Test *test = user_data;
223
224 tp_proxy_prepare_finish (source, result, &test->error);
225
226 test->wait--;
227 if (test->wait <= 0)
228 g_main_loop_quit (test->mainloop);
229 }
230
231 static void
test_can_report_abusive(Test * test,gconstpointer data G_GNUC_UNUSED)232 test_can_report_abusive (Test *test,
233 gconstpointer data G_GNUC_UNUSED)
234 {
235 GQuark features[] = { TP_CONNECTION_FEATURE_CONTACT_BLOCKING, 0 };
236 gboolean abuse;
237
238 /* Feature is not prepared yet */
239 g_object_get (test->connection, "can-report-abusive", &abuse, NULL);
240 g_assert (!abuse);
241 g_assert (!tp_connection_can_report_abusive (test->connection));
242
243 tp_proxy_prepare_async (test->connection, features,
244 proxy_prepare_cb, test);
245
246 test->wait = 1;
247 g_main_loop_run (test->mainloop);
248 g_assert_no_error (test->error);
249
250 g_assert (tp_proxy_is_prepared (test->connection,
251 TP_CONNECTION_FEATURE_CONTACT_BLOCKING));
252
253 g_object_get (test->connection, "can-report-abusive", &abuse, NULL);
254 g_assert (abuse);
255 g_assert (tp_connection_can_report_abusive (test->connection));
256 }
257
258 static void
blocked_contacts_changed_cb(TpConnection * conn,GPtrArray * added,GPtrArray * removed,Test * test)259 blocked_contacts_changed_cb (TpConnection *conn,
260 GPtrArray *added,
261 GPtrArray *removed,
262 Test *test)
263 {
264 tp_clear_pointer (&test->blocked_added, g_ptr_array_unref);
265 tp_clear_pointer (&test->blocked_removed, g_ptr_array_unref);
266
267 test->blocked_added = g_ptr_array_ref (added);
268 test->blocked_removed = g_ptr_array_ref (removed);
269
270 test->wait--;
271 if (test->wait <= 0)
272 g_main_loop_quit (test->mainloop);
273 }
274
275 static void
test_blocked_contacts(Test * test,gconstpointer data G_GNUC_UNUSED)276 test_blocked_contacts (Test *test,
277 gconstpointer data G_GNUC_UNUSED)
278 {
279 GQuark features[] = { TP_CONNECTION_FEATURE_CONTACT_BLOCKING, 0 };
280 GPtrArray *blocked;
281 TpContact *alice, *bill, *guillaume, *sjoerd, *steve;
282 gboolean use_contact_api = GPOINTER_TO_UINT (data);
283
284 sjoerd = create_contact (test, "sjoerd@example.com");
285 steve = create_contact (test, "steve@example.com");
286
287 /* Feature is not prepared yet */
288 g_object_get (test->connection, "blocked-contacts", &blocked, NULL);
289 g_assert_cmpuint (blocked->len, == , 0);
290 g_ptr_array_unref (blocked);
291
292 blocked = tp_connection_get_blocked_contacts (test->connection);
293 g_assert_cmpuint (blocked->len, == , 0);
294
295 /* Prepare the feature */
296 tp_proxy_prepare_async (test->connection, features,
297 proxy_prepare_cb, test);
298
299 test->wait = 1;
300 g_main_loop_run (test->mainloop);
301 g_assert_no_error (test->error);
302
303 /* 2 contacts are already blocked in the CM */
304 g_object_get (test->connection, "blocked-contacts", &blocked, NULL);
305 g_assert_cmpuint (blocked->len, == , 2);
306 g_ptr_array_unref (blocked);
307
308 blocked = tp_connection_get_blocked_contacts (test->connection);
309 g_assert_cmpuint (blocked->len, == , 2);
310
311 /* Preparing TP_CONNECTION_FEATURE_CONTACT_BLOCKING gives us
312 * TP_CONTACT_FEATURE_CONTACT_BLOCKING for free. Test that this works with
313 * existing and newly created TpContact. */
314 bill = create_contact (test, "bill@example.com");
315 guillaume = create_contact (test, "guillaume@example.com");
316
317 g_assert (tp_contact_has_feature (sjoerd,
318 TP_CONTACT_FEATURE_CONTACT_BLOCKING));
319 g_assert (!tp_contact_is_blocked (sjoerd));
320
321 g_assert (tp_contact_has_feature (steve,
322 TP_CONTACT_FEATURE_CONTACT_BLOCKING));
323 g_assert (tp_contact_is_blocked (steve));
324
325 g_assert (tp_contact_has_feature (bill, TP_CONTACT_FEATURE_CONTACT_BLOCKING));
326 g_assert (tp_contact_is_blocked (bill));
327
328 g_assert (tp_contact_has_feature (guillaume,
329 TP_CONTACT_FEATURE_CONTACT_BLOCKING));
330 g_assert (!tp_contact_is_blocked (guillaume));
331
332 g_object_unref (steve);
333 g_object_unref (sjoerd);
334 g_object_unref (bill);
335 g_object_unref (guillaume);
336
337 /* Let's block another contact */
338 alice = create_contact (test, "alice");
339
340 g_signal_connect (test->connection, "blocked-contacts-changed",
341 G_CALLBACK (blocked_contacts_changed_cb), test);
342
343 if (use_contact_api)
344 {
345 tp_contact_block_async (alice, FALSE, contact_block_cb, test);
346 }
347 else
348 {
349 tp_connection_block_contacts_async (test->connection,
350 1, &alice, FALSE, block_contacts_cb, test);
351 }
352
353 g_object_unref (alice);
354
355 test->wait = 2;
356 g_main_loop_run (test->mainloop);
357 g_assert_no_error (test->error);
358
359 g_assert_cmpuint (test->blocked_added->len, ==, 1);
360 g_assert_cmpuint (test->blocked_removed->len, ==, 0);
361
362 alice = g_ptr_array_index (test->blocked_added, 0);
363 g_assert (TP_IS_CONTACT (alice));
364 g_assert_cmpstr (tp_contact_get_identifier (alice), ==, "alice");
365
366 blocked = tp_connection_get_blocked_contacts (test->connection);
367 g_assert_cmpuint (blocked->len, == , 3);
368
369 /* Cool, now unblock the poor Alice */
370 if (use_contact_api)
371 {
372 tp_contact_unblock_async (alice, contact_unblock_cb, test);
373 }
374 else
375 {
376 tp_connection_unblock_contacts_async (test->connection,
377 1, &alice, unblock_contacts_cb, test);
378 }
379
380 test->wait = 2;
381 g_main_loop_run (test->mainloop);
382 g_assert_no_error (test->error);
383
384 g_assert_cmpuint (test->blocked_added->len, ==, 0);
385 g_assert_cmpuint (test->blocked_removed->len, ==, 1);
386
387 alice = g_ptr_array_index (test->blocked_removed, 0);
388 g_assert (TP_IS_CONTACT (alice));
389 g_assert_cmpstr (tp_contact_get_identifier (alice), ==, "alice");
390
391 blocked = tp_connection_get_blocked_contacts (test->connection);
392 g_assert_cmpuint (blocked->len, == , 2);
393 }
394
395 static void
get_contacts_by_id_cb(TpConnection * connection,guint n_contacts,TpContact * const * contacts,const gchar * const * requested_ids,GHashTable * failed_id_errors,const GError * error,gpointer user_data,GObject * weak_object)396 get_contacts_by_id_cb (TpConnection *connection,
397 guint n_contacts,
398 TpContact * const *contacts,
399 const gchar * const *requested_ids,
400 GHashTable *failed_id_errors,
401 const GError *error,
402 gpointer user_data,
403 GObject *weak_object)
404 {
405 Test *test = user_data;
406
407 g_clear_object (&test->contact);
408
409 if (error != NULL)
410 {
411 test->error = g_error_copy (error);
412 }
413 else
414 {
415 test->contact = g_object_ref (contacts[0]);
416 }
417
418 test->wait--;
419 if (test->wait <= 0)
420 g_main_loop_quit (test->mainloop);
421 }
422
423 static void
contact_list_state_change_cb(GObject * object,GParamSpec * pspec,gpointer user_data)424 contact_list_state_change_cb (GObject *object,
425 GParamSpec *pspec,
426 gpointer user_data)
427 {
428 TpConnection *conn = (TpConnection *) object;
429 Test *test = user_data;
430
431 if (tp_connection_get_contact_list_state (conn) !=
432 TP_CONTACT_LIST_STATE_SUCCESS)
433 return;
434
435 test->wait--;
436 if (test->wait <= 0)
437 g_main_loop_quit (test->mainloop);
438 }
439
440 static void
property_change_cb(GObject * object,GParamSpec * pspec,gpointer user_data)441 property_change_cb (GObject *object,
442 GParamSpec *pspec,
443 gpointer user_data)
444 {
445 Test *test = user_data;
446
447 test->wait--;
448 if (test->wait <= 0)
449 g_main_loop_quit (test->mainloop);
450 }
451
452 static void
test_is_blocked(Test * test,gconstpointer data G_GNUC_UNUSED)453 test_is_blocked (Test *test,
454 gconstpointer data G_GNUC_UNUSED)
455 {
456 const gchar *id = "bill@example.com";
457 TpContactFeature features[] = { TP_CONTACT_FEATURE_CONTACT_BLOCKING };
458 GQuark conn_features[] = { TP_CONNECTION_FEATURE_CONTACT_LIST, 0 };
459
460 tp_proxy_prepare_async (test->connection, conn_features,
461 proxy_prepare_cb, test);
462
463 test->wait = 1;
464
465 /* We have to wait that the ContactList has been fetched by the CM */
466 if (tp_connection_get_contact_list_state (test->connection) !=
467 TP_CONTACT_LIST_STATE_SUCCESS)
468 {
469 g_signal_connect (test->connection, "notify::contact-list-state",
470 G_CALLBACK (contact_list_state_change_cb), test);
471
472 test->wait++;
473 }
474
475 g_main_loop_run (test->mainloop);
476 g_assert_no_error (test->error);
477
478 /* Bill is already blocked in the CM */
479 tp_connection_get_contacts_by_id (test->connection, 1, &id,
480 G_N_ELEMENTS (features), features, get_contacts_by_id_cb, test,
481 NULL, NULL);
482
483 test->wait = 1;
484 g_main_loop_run (test->mainloop);
485 g_assert_no_error (test->error);
486
487 g_assert (TP_IS_CONTACT (test->contact));
488
489 g_assert (tp_contact_has_feature (test->contact,
490 TP_CONTACT_FEATURE_CONTACT_BLOCKING));
491 g_assert (tp_contact_is_blocked (test->contact));
492
493 /* Unblock Bill */
494 g_signal_connect (test->contact, "notify::is-blocked",
495 G_CALLBACK (property_change_cb), test);
496
497 tp_contact_unblock_async (test->contact, contact_unblock_cb, test);
498
499 test->wait = 2;
500 g_main_loop_run (test->mainloop);
501 g_assert_no_error (test->error);
502
503 g_assert (!tp_contact_is_blocked (test->contact));
504 }
505
506 static void
test_contact_list_properties(Test * test,gconstpointer data G_GNUC_UNUSED)507 test_contact_list_properties (Test *test,
508 gconstpointer data G_GNUC_UNUSED)
509 {
510 gboolean props_only = GPOINTER_TO_UINT (data);
511 GQuark conn_features[] = { 0, 0 };
512 GPtrArray *contacts;
513
514 if (props_only)
515 conn_features[0] = TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES;
516 else
517 conn_features[0] = TP_CONNECTION_FEATURE_CONTACT_LIST;
518
519 /* Feature isn't prepared yet */
520 g_assert (!tp_proxy_is_prepared (test->connection,
521 TP_CONNECTION_FEATURE_CONTACT_LIST));
522 g_assert (!tp_proxy_is_prepared (test->connection,
523 TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES));
524
525 g_assert_cmpuint (tp_connection_get_contact_list_state (test->connection), ==,
526 TP_CONTACT_LIST_STATE_NONE);
527 g_assert (!tp_connection_get_contact_list_persists (test->connection));
528 g_assert (!tp_connection_get_can_change_contact_list (test->connection));
529 g_assert (!tp_connection_get_request_uses_message (test->connection));
530
531 tp_proxy_prepare_async (test->connection, conn_features,
532 proxy_prepare_cb, test);
533
534 test->wait = 1;
535 g_main_loop_run (test->mainloop);
536 g_assert_no_error (test->error);
537
538 g_assert (tp_proxy_is_prepared (test->connection,
539 TP_CONNECTION_FEATURE_CONTACT_LIST) == !props_only);
540 g_assert (tp_proxy_is_prepared (test->connection,
541 TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES));
542
543 g_assert (tp_connection_get_contact_list_persists (test->connection));
544 g_assert (tp_connection_get_can_change_contact_list (test->connection));
545 g_assert (tp_connection_get_request_uses_message (test->connection));
546
547 contacts = tp_connection_dup_contact_list (test->connection);
548 if (props_only)
549 {
550 /* Contacts haven't be fetched */
551 g_assert_cmpuint (contacts->len, ==, 0);
552 }
553 else
554 {
555 g_assert_cmpuint (contacts->len, >, 0);
556 }
557 g_ptr_array_unref (contacts);
558 }
559
560 int
main(int argc,char ** argv)561 main (int argc,
562 char **argv)
563 {
564 tp_tests_init (&argc, &argv);
565 g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
566
567 g_test_add ("/contact-list-client/blocking/block-unblock", Test, NULL, setup,
568 test_block_unblock, teardown);
569 g_test_add ("/contact-list-client/blocking/can-report-abusive", Test, NULL,
570 setup, test_can_report_abusive, teardown);
571 g_test_add ("/contact-list-client/blocking/connection/blocked-contacts", Test,
572 GUINT_TO_POINTER (FALSE), setup, test_blocked_contacts, teardown);
573 g_test_add ("/contact-list-client/blocking/contact/blocked-contacts", Test,
574 GUINT_TO_POINTER (TRUE), setup, test_blocked_contacts, teardown);
575 g_test_add ("/contact-list-client/blocking/is-blocked", Test, NULL,
576 setup, test_is_blocked, teardown);
577
578 g_test_add ("/contact-list-client/contact-list/properties", Test,
579 GUINT_TO_POINTER (FALSE), setup, test_contact_list_properties, teardown);
580 g_test_add ("/contact-list-client/contact-list/properties", Test,
581 GUINT_TO_POINTER (TRUE), setup, test_contact_list_properties, teardown);
582
583 return tp_tests_run_with_bus ();
584 }
585