1 /* Tests of TpChannel
2  * TODO: tests/dbus/channel-introspect.c should probably move here at some
3  * point
4  *
5  * Copyright © 2010 Collabora Ltd. <http://www.collabora.co.uk/>
6  *
7  * Copying and distribution of this file, with or without modification,
8  * are permitted in any medium without royalty provided the copyright
9  * notice and this notice are preserved.
10  */
11 
12 #include "config.h"
13 
14 #include <string.h>
15 
16 #include <telepathy-glib/telepathy-glib.h>
17 
18 #include "tests/lib/util.h"
19 #include "tests/lib/contacts-conn.h"
20 #include "tests/lib/textchan-null.h"
21 #include "tests/lib/textchan-group.h"
22 
23 typedef struct {
24     GMainLoop *mainloop;
25     TpDBusDaemon *dbus;
26 
27     /* Service side objects */
28     TpBaseConnection *base_connection;
29     TpTestsTextChannelNull *chan_contact_service;
30     TpTestsTextChannelGroup *chan_room_service;
31     TpHandleRepoIface *contact_repo;
32     TpHandleRepoIface *room_repo;
33 
34     /* Client side objects */
35     TpConnection *connection;
36     TpChannel *channel_contact;
37     TpChannel *channel_room;
38 
39     GError *error /* initialized where needed */;
40     gint wait;
41 } Test;
42 
43 static void
create_contact_chan(Test * test)44 create_contact_chan (Test *test)
45 {
46   gchar *chan_path;
47   TpHandle handle;
48   GHashTable *props;
49 
50   tp_clear_object (&test->chan_contact_service);
51   tp_clear_object (&test->chan_room_service);
52 
53   /* Create service-side channel object */
54   chan_path = g_strdup_printf ("%s/Channel",
55       tp_proxy_get_object_path (test->connection));
56 
57   test->contact_repo = tp_base_connection_get_handles (test->base_connection,
58       TP_HANDLE_TYPE_CONTACT);
59   g_assert (test->contact_repo != NULL);
60 
61   handle = tp_handle_ensure (test->contact_repo, "bob", NULL, &test->error);
62 
63   g_assert_no_error (test->error);
64 
65   test->chan_contact_service = tp_tests_object_new_static_class (
66       TP_TESTS_TYPE_TEXT_CHANNEL_NULL,
67       "connection", test->base_connection,
68       "handle", handle,
69       "object-path", chan_path,
70       NULL);
71 
72   props = tp_tests_text_channel_get_props (test->chan_contact_service);
73 
74   test->channel_contact = tp_channel_new_from_properties (test->connection,
75       chan_path, props, &test->error);
76   g_assert_no_error (test->error);
77 
78   g_free (chan_path);
79 
80   tp_handle_unref (test->contact_repo, handle);
81   g_hash_table_unref (props);
82 }
83 
84 static void
create_room_chan(Test * test)85 create_room_chan (Test *test)
86 {
87   gchar *chan_path;
88   GHashTable *props;
89 
90   tp_clear_object (&test->chan_room_service);
91 
92   /* Create service-side channel object */
93   chan_path = g_strdup_printf ("%s/Channel2",
94       tp_proxy_get_object_path (test->connection));
95 
96   test->room_repo = tp_base_connection_get_handles (test->base_connection,
97       TP_HANDLE_TYPE_ROOM);
98   g_assert (test->room_repo != NULL);
99 
100   test->chan_room_service = tp_tests_object_new_static_class (
101       TP_TESTS_TYPE_TEXT_CHANNEL_GROUP,
102       "connection", test->base_connection,
103       "object-path", chan_path,
104       NULL);
105 
106   g_object_get (test->chan_room_service,
107       "channel-properties", &props,
108       NULL);
109 
110   test->channel_room = tp_channel_new_from_properties (test->connection,
111       chan_path, props, &test->error);
112   g_assert_no_error (test->error);
113 
114   /* We are in the muc */
115   tp_tests_text_channel_group_join (test->chan_room_service);
116 
117   g_free (chan_path);
118 
119   g_hash_table_unref (props);
120 }
121 
122 static void
setup(Test * test,gconstpointer data)123 setup (Test *test,
124        gconstpointer data)
125 {
126   test->mainloop = g_main_loop_new (NULL, FALSE);
127   test->dbus = tp_tests_dbus_daemon_dup_or_die ();
128 
129   test->error = NULL;
130 
131   /* Create (service and client sides) connection objects */
132   tp_tests_create_and_connect_conn (TP_TESTS_TYPE_CONTACTS_CONNECTION,
133       "me@test.com", &test->base_connection, &test->connection);
134 
135   create_contact_chan (test);
136   create_room_chan (test);
137 }
138 
139 static void
teardown(Test * test,gconstpointer data)140 teardown (Test *test,
141           gconstpointer data)
142 {
143   g_clear_error (&test->error);
144 
145   tp_clear_object (&test->dbus);
146   g_main_loop_unref (test->mainloop);
147   test->mainloop = NULL;
148 
149   tp_clear_object (&test->chan_contact_service);
150   tp_clear_object (&test->chan_room_service);
151 
152   tp_tests_connection_assert_disconnect_succeeds (test->connection);
153   g_object_unref (test->connection);
154   g_object_unref (test->base_connection);
155 
156   tp_clear_object (&test->channel_contact);
157   tp_clear_object (&test->channel_room);
158 }
159 
160 static void
channel_leave_cb(GObject * source,GAsyncResult * result,gpointer user_data)161 channel_leave_cb (GObject *source,
162     GAsyncResult *result,
163     gpointer user_data)
164 {
165   Test *test = user_data;
166 
167   tp_channel_leave_finish (TP_CHANNEL (source), result, &test->error);
168 
169   test->wait--;
170   if (test->wait <= 0)
171     g_main_loop_quit (test->mainloop);
172 }
173 
174 static void
test_leave_contact_unprepared_no_reason(Test * test,gconstpointer data G_GNUC_UNUSED)175 test_leave_contact_unprepared_no_reason (Test *test,
176     gconstpointer data G_GNUC_UNUSED)
177 {
178   g_assert (tp_proxy_get_invalidated (test->channel_contact) == NULL);
179 
180   tp_channel_leave_async (test->channel_contact,
181       TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
182       NULL, channel_leave_cb, test);
183 
184   g_main_loop_run (test->mainloop);
185   g_assert_no_error (test->error);
186 
187   g_assert (tp_proxy_get_invalidated (test->channel_contact) != NULL);
188 }
189 
190 static void
test_leave_contact_unprepared_reason(Test * test,gconstpointer data G_GNUC_UNUSED)191 test_leave_contact_unprepared_reason (Test *test,
192     gconstpointer data G_GNUC_UNUSED)
193 {
194   g_assert (tp_proxy_get_invalidated (test->channel_contact) == NULL);
195 
196   tp_channel_leave_async (test->channel_contact,
197       TP_CHANNEL_GROUP_CHANGE_REASON_BUSY,
198       "Bye Bye", channel_leave_cb, test);
199 
200   g_main_loop_run (test->mainloop);
201   g_assert_no_error (test->error);
202 
203   g_assert (tp_proxy_get_invalidated (test->channel_contact) != NULL);
204 }
205 
206 static void
channel_prepared_cb(GObject * source,GAsyncResult * result,gpointer user_data)207 channel_prepared_cb (GObject *source,
208     GAsyncResult *result,
209     gpointer user_data)
210 {
211   Test *test = user_data;
212 
213   tp_proxy_prepare_finish (source, result, &test->error);
214 
215   test->wait--;
216   if (test->wait <= 0)
217     g_main_loop_quit (test->mainloop);
218 }
219 
220 static void
test_leave_contact_prepared_no_reason(Test * test,gconstpointer data G_GNUC_UNUSED)221 test_leave_contact_prepared_no_reason (Test *test,
222     gconstpointer data G_GNUC_UNUSED)
223 {
224   GQuark features[] = { TP_CHANNEL_FEATURE_CORE, 0 };
225 
226   g_assert (tp_proxy_get_invalidated (test->channel_contact) == NULL);
227 
228   tp_proxy_prepare_async (test->channel_contact, features,
229       channel_prepared_cb, test);
230   g_main_loop_run (test->mainloop);
231   g_assert_no_error (test->error);
232 
233   tp_channel_leave_async (test->channel_contact,
234       TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
235       NULL, channel_leave_cb, test);
236 
237   g_main_loop_run (test->mainloop);
238   g_assert_no_error (test->error);
239 
240   g_assert (tp_proxy_get_invalidated (test->channel_contact) != NULL);
241 }
242 
243 static void
test_leave_contact_prepared_reason(Test * test,gconstpointer data G_GNUC_UNUSED)244 test_leave_contact_prepared_reason (Test *test,
245     gconstpointer data G_GNUC_UNUSED)
246 {
247   GQuark features[] = { TP_CHANNEL_FEATURE_CORE, 0 };
248 
249   g_assert (tp_proxy_get_invalidated (test->channel_contact) == NULL);
250 
251   tp_proxy_prepare_async (test->channel_contact, features,
252       channel_prepared_cb, test);
253   g_main_loop_run (test->mainloop);
254   g_assert_no_error (test->error);
255 
256   tp_channel_leave_async (test->channel_contact,
257       TP_CHANNEL_GROUP_CHANGE_REASON_BUSY,
258       "Bye Bye", channel_leave_cb, test);
259 
260   g_main_loop_run (test->mainloop);
261   g_assert_no_error (test->error);
262 
263   g_assert (tp_proxy_get_invalidated (test->channel_contact) != NULL);
264 }
265 
266 /* Room tests */
267 static void
check_not_removed(TpTestsTextChannelGroup * chan)268 check_not_removed (TpTestsTextChannelGroup *chan)
269 {
270   g_assert_cmpuint (chan->removed_handle, ==, 0);
271   g_assert (chan->removed_message == NULL);
272   g_assert_cmpuint (chan->removed_reason, ==, 0);
273 }
274 
275 static void
check_removed(TpTestsTextChannelGroup * chan)276 check_removed (TpTestsTextChannelGroup *chan)
277 {
278   g_assert_cmpuint (chan->removed_handle, !=, 0);
279   g_assert_cmpstr (chan->removed_message, ==, "Bye Bye");
280   g_assert_cmpuint (chan->removed_reason, ==,
281       TP_CHANNEL_GROUP_CHANGE_REASON_BUSY);
282 }
283 
284 static void
test_leave_room_unprepared_no_reason(Test * test,gconstpointer data G_GNUC_UNUSED)285 test_leave_room_unprepared_no_reason (Test *test,
286     gconstpointer data G_GNUC_UNUSED)
287 {
288   g_assert (tp_proxy_get_invalidated (test->channel_room) == NULL);
289 
290   tp_channel_leave_async (test->channel_room,
291       TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
292       NULL, channel_leave_cb, test);
293 
294   g_main_loop_run (test->mainloop);
295   g_assert_no_error (test->error);
296 
297   g_assert (tp_proxy_get_invalidated (test->channel_room) != NULL);
298   g_assert_cmpuint (test->chan_room_service->removed_handle, !=, 0);
299   g_assert_cmpstr (test->chan_room_service->removed_message, ==, "");
300   g_assert_cmpuint (test->chan_room_service->removed_reason, ==,
301       TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
302 }
303 
304 static void
test_leave_room_unprepared_reason(Test * test,gconstpointer data G_GNUC_UNUSED)305 test_leave_room_unprepared_reason (Test *test,
306     gconstpointer data G_GNUC_UNUSED)
307 {
308   g_assert (tp_proxy_get_invalidated (test->channel_room) == NULL);
309 
310   tp_channel_leave_async (test->channel_room,
311       TP_CHANNEL_GROUP_CHANGE_REASON_BUSY,
312       "Bye Bye", channel_leave_cb, test);
313 
314   g_main_loop_run (test->mainloop);
315   g_assert_no_error (test->error);
316 
317   g_assert (tp_proxy_get_invalidated (test->channel_room) != NULL);
318   check_removed (test->chan_room_service);
319 }
320 
321 static void
test_leave_room_prepared_no_reason(Test * test,gconstpointer data G_GNUC_UNUSED)322 test_leave_room_prepared_no_reason (Test *test,
323     gconstpointer data G_GNUC_UNUSED)
324 {
325   GQuark features[] = { TP_CHANNEL_FEATURE_CORE, 0 };
326 
327   g_assert (tp_proxy_get_invalidated (test->channel_room) == NULL);
328 
329   tp_proxy_prepare_async (test->channel_room, features,
330       channel_prepared_cb, test);
331   g_main_loop_run (test->mainloop);
332   g_assert_no_error (test->error);
333 
334   tp_channel_leave_async (test->channel_room,
335       TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
336       NULL, channel_leave_cb, test);
337 
338   g_main_loop_run (test->mainloop);
339   g_assert_no_error (test->error);
340 
341   g_assert (tp_proxy_get_invalidated (test->channel_room) != NULL);
342   g_assert_cmpuint (test->chan_room_service->removed_handle, !=, 0);
343   g_assert_cmpstr (test->chan_room_service->removed_message, ==, "");
344   g_assert_cmpuint (test->chan_room_service->removed_reason, ==,
345       TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
346 }
347 
348 static void
test_leave_room_prepared_reason(Test * test,gconstpointer data G_GNUC_UNUSED)349 test_leave_room_prepared_reason (Test *test,
350     gconstpointer data G_GNUC_UNUSED)
351 {
352   GQuark features[] = { TP_CHANNEL_FEATURE_CORE, 0 };
353 
354   g_assert (tp_proxy_get_invalidated (test->channel_room) == NULL);
355 
356   tp_proxy_prepare_async (test->channel_room, features,
357       channel_prepared_cb, test);
358   g_main_loop_run (test->mainloop);
359   g_assert_no_error (test->error);
360 
361   tp_channel_leave_async (test->channel_room,
362       TP_CHANNEL_GROUP_CHANGE_REASON_BUSY,
363       "Bye Bye", channel_leave_cb, test);
364 
365   g_main_loop_run (test->mainloop);
366   g_assert_no_error (test->error);
367 
368   g_assert (tp_proxy_get_invalidated (test->channel_room) != NULL);
369   check_removed (test->chan_room_service);
370 }
371 
372 static void
channel_close_cb(GObject * source,GAsyncResult * result,gpointer user_data)373 channel_close_cb (GObject *source,
374     GAsyncResult *result,
375     gpointer user_data)
376 {
377   Test *test = user_data;
378 
379   tp_channel_close_finish (TP_CHANNEL (source), result, &test->error);
380 
381   test->wait--;
382   if (test->wait <= 0)
383     g_main_loop_quit (test->mainloop);
384 }
385 
386 static void
test_close(Test * test,gconstpointer data G_GNUC_UNUSED)387 test_close (Test *test,
388     gconstpointer data G_GNUC_UNUSED)
389 {
390   g_assert (tp_proxy_get_invalidated (test->channel_contact) == NULL);
391 
392   tp_channel_close_async (test->channel_contact, channel_close_cb, test);
393 
394   g_main_loop_run (test->mainloop);
395   g_assert_no_error (test->error);
396 
397   g_assert (tp_proxy_get_invalidated (test->channel_contact) != NULL);
398 }
399 
400 static void
test_close_room(Test * test,gconstpointer data G_GNUC_UNUSED)401 test_close_room (Test *test,
402     gconstpointer data G_GNUC_UNUSED)
403 {
404   g_assert (tp_proxy_get_invalidated (test->channel_room) == NULL);
405 
406   tp_channel_close_async (test->channel_room, channel_close_cb, test);
407 
408   g_main_loop_run (test->mainloop);
409   g_assert_no_error (test->error);
410 
411   g_assert (tp_proxy_get_invalidated (test->channel_room) != NULL);
412   check_not_removed (test->chan_room_service);
413 }
414 
415 static void
channel_destroy_cb(GObject * source,GAsyncResult * result,gpointer user_data)416 channel_destroy_cb (GObject *source,
417     GAsyncResult *result,
418     gpointer user_data)
419 {
420   Test *test = user_data;
421 
422   tp_channel_destroy_finish (TP_CHANNEL (source), result, &test->error);
423 
424   test->wait--;
425   if (test->wait <= 0)
426     g_main_loop_quit (test->mainloop);
427 }
428 
429 static void
test_destroy(Test * test,gconstpointer data G_GNUC_UNUSED)430 test_destroy (Test *test,
431     gconstpointer data G_GNUC_UNUSED)
432 {
433   g_assert (tp_proxy_get_invalidated (test->channel_contact) == NULL);
434 
435   tp_channel_destroy_async (test->channel_contact, channel_destroy_cb, test);
436 
437   g_main_loop_run (test->mainloop);
438   g_assert_no_error (test->error);
439 
440   g_assert (tp_proxy_get_invalidated (test->channel_contact) != NULL);
441 }
442 
443 static void
property_changed_cb(GObject * object,GParamSpec * spec,Test * test)444 property_changed_cb (GObject *object,
445     GParamSpec *spec,
446     Test *test)
447 {
448   test->wait--;
449   if (test->wait <= 0)
450     g_main_loop_quit (test->mainloop);
451 }
452 
453 static void
test_password_feature(Test * test,gconstpointer data G_GNUC_UNUSED)454 test_password_feature (Test *test,
455     gconstpointer data G_GNUC_UNUSED)
456 {
457   GQuark features[] = { TP_CHANNEL_FEATURE_PASSWORD, 0 };
458   gboolean pass_needed;
459 
460   /* Channel needs a password */
461   tp_tests_text_channel_set_password (test->chan_room_service, "test");
462 
463   /* Feature is not yet prepared */
464   g_assert (!tp_channel_password_needed (test->channel_room));
465   g_object_get (test->channel_room, "password-needed", &pass_needed, NULL);
466   g_assert (!pass_needed);
467 
468   g_signal_connect (test->channel_room, "notify::password-needed",
469       G_CALLBACK (property_changed_cb), test);
470 
471   tp_proxy_prepare_async (test->channel_room, features, channel_prepared_cb,
472       test);
473 
474   test->wait = 2;
475   g_main_loop_run (test->mainloop);
476   g_assert_no_error (test->error);
477 
478   g_assert (tp_channel_password_needed (test->channel_room));
479   g_object_get (test->channel_room, "password-needed", &pass_needed, NULL);
480   g_assert (pass_needed);
481 
482   /* Channel does not need a password any more */
483   tp_tests_text_channel_set_password (test->chan_room_service, NULL);
484 
485   test->wait = 1;
486   g_main_loop_run (test->mainloop);
487   g_assert_no_error (test->error);
488 
489   g_assert (!tp_channel_password_needed (test->channel_room));
490   g_object_get (test->channel_room, "password-needed", &pass_needed, NULL);
491   g_assert (!pass_needed);
492 
493   /* Channel does not re-need a password */
494   tp_tests_text_channel_set_password (test->chan_room_service, "test");
495 
496   test->wait = 1;
497   g_main_loop_run (test->mainloop);
498   g_assert_no_error (test->error);
499 
500   g_assert (tp_channel_password_needed (test->channel_room));
501   g_object_get (test->channel_room, "password-needed", &pass_needed, NULL);
502   g_assert (pass_needed);
503 }
504 
505 static void
provide_password_cb(GObject * source,GAsyncResult * result,gpointer user_data)506 provide_password_cb (GObject *source,
507     GAsyncResult *result,
508     gpointer user_data)
509 {
510   Test *test = user_data;
511 
512   g_clear_error (&test->error);
513 
514   tp_channel_provide_password_finish (TP_CHANNEL (source), result,
515       &test->error);
516 
517   test->wait--;
518   if (test->wait <= 0)
519     g_main_loop_quit (test->mainloop);
520 }
521 
522 static void
test_password_provide(Test * test,gconstpointer data G_GNUC_UNUSED)523 test_password_provide (Test *test,
524     gconstpointer data G_GNUC_UNUSED)
525 {
526   tp_tests_text_channel_set_password (test->chan_room_service, "test");
527 
528   /* Try a wrong password */
529   tp_channel_provide_password_async (test->channel_room, "badger",
530       provide_password_cb, test);
531 
532   test->wait = 1;
533   g_main_loop_run (test->mainloop);
534   g_assert_error (test->error, TP_ERROR, TP_ERROR_AUTHENTICATION_FAILED);
535 
536   /* Try the right password */
537   tp_channel_provide_password_async (test->channel_room, "test",
538       provide_password_cb, test);
539 
540   test->wait = 1;
541   g_main_loop_run (test->mainloop);
542   g_assert_no_error (test->error);
543 }
544 
545 static void
join_cb(GObject * source,GAsyncResult * result,gpointer user_data)546 join_cb (GObject *source,
547     GAsyncResult *result,
548     gpointer user_data)
549 {
550   Test *test = user_data;
551 
552   tp_channel_join_finish (TP_CHANNEL (source), result, &test->error);
553 
554   test->wait--;
555   if (test->wait <= 0)
556     g_main_loop_quit (test->mainloop);
557 }
558 
559 static void
test_join_room(Test * test,gconstpointer data G_GNUC_UNUSED)560 test_join_room (Test *test,
561     gconstpointer data G_GNUC_UNUSED)
562 {
563   GQuark features[] = { TP_CHANNEL_FEATURE_GROUP, 0 };
564 
565   tp_proxy_prepare_async (test->channel_room, features,
566       channel_prepared_cb, test);
567   g_main_loop_run (test->mainloop);
568   g_assert_no_error (test->error);
569 
570   tp_channel_join_async (test->channel_room, "Hello World",
571       join_cb, test);
572 
573   test->wait = 1;
574   g_main_loop_run (test->mainloop);
575   g_assert_no_error (test->error);
576 }
577 
578 static void
group_contacts_changed_cb(TpChannel * self,GPtrArray * added,GPtrArray * removed,GPtrArray * local_pending,GPtrArray * remote_pending,TpContact * actor,GHashTable * details,Test * test)579 group_contacts_changed_cb (TpChannel *self,
580     GPtrArray *added,
581     GPtrArray *removed,
582     GPtrArray *local_pending,
583     GPtrArray *remote_pending,
584     TpContact *actor,
585     GHashTable *details,
586     Test *test)
587 {
588   test->wait--;
589   if (test->wait <= 0)
590     g_main_loop_quit (test->mainloop);
591 }
592 
593 static void
test_contacts(Test * test,gconstpointer data G_GNUC_UNUSED)594 test_contacts (Test *test,
595     gconstpointer data G_GNUC_UNUSED)
596 {
597   TpSimpleClientFactory *factory;
598   const gchar *id = "badger";
599   const gchar *alias1 = "Alias 1";
600   const gchar *alias2 = "Alias 2";
601   GQuark channel_features[] = { TP_CHANNEL_FEATURE_CONTACTS, 0 };
602   TpHandle handle;
603   GArray *handles;
604   TpContact *contact;
605   GPtrArray *contacts;
606 
607   /* Tell factory we want to prepare ALIAS feature on TpContact objects */
608   factory = tp_proxy_get_factory (test->connection);
609   tp_simple_client_factory_add_contact_features_varargs (factory,
610       TP_CONTACT_FEATURE_ALIAS,
611       TP_CONTACT_FEATURE_INVALID);
612 
613   /* Set an alias for channel's target contact */
614   handle = tp_channel_get_handle (test->channel_contact, NULL);
615   g_assert (handle != 0);
616   tp_tests_contacts_connection_change_aliases (
617       TP_TESTS_CONTACTS_CONNECTION (test->base_connection),
618       1, &handle, &alias1);
619 
620   /* Prepare channel with CONTACTS feature. assert it has created its TpContact
621    * and prepared alias feature. */
622   tp_tests_proxy_run_until_prepared (test->channel_contact, channel_features);
623 
624   contact = tp_channel_get_target_contact (test->channel_contact);
625   g_assert_cmpstr (tp_contact_get_identifier (contact), ==, "bob");
626   g_assert_cmpstr (tp_contact_get_alias (contact), ==, alias1);
627 
628   contact = tp_channel_get_initiator_contact (test->channel_contact);
629   g_assert_cmpstr (tp_contact_get_identifier (contact), ==, "me@test.com");
630 
631   /* Prepare room channel and assert it prepared the self contact */
632   tp_tests_proxy_run_until_prepared (test->channel_room, channel_features);
633 
634   contact = tp_channel_group_get_self_contact (test->channel_room);
635   g_assert_cmpstr (tp_contact_get_identifier (contact), ==, "me@test.com");
636 
637   /* Add a member in the room, assert that the member fetched its alias before
638    * being signaled. */
639   handle = tp_handle_ensure (test->contact_repo, id, NULL, NULL);
640   tp_tests_contacts_connection_change_aliases (
641       TP_TESTS_CONTACTS_CONNECTION (test->base_connection),
642       1, &handle, &alias2);
643 
644   g_signal_connect (test->channel_room, "group-contacts-changed",
645       G_CALLBACK (group_contacts_changed_cb), test);
646 
647   handles = g_array_new (FALSE, FALSE, sizeof (TpHandle));
648   g_array_append_val (handles, handle);
649   tp_cli_channel_interface_group_call_add_members (test->channel_room, -1,
650       handles, "hello", NULL, NULL, NULL, NULL);
651   g_array_unref (handles);
652 
653   g_main_loop_run (test->mainloop);
654 
655   /* There is ourself and the new contact, get the new one */
656   contacts = tp_channel_group_dup_members_contacts (test->channel_room);
657   g_assert (contacts != NULL);
658   g_assert (contacts->len == 2);
659   contact = g_ptr_array_index (contacts, 0);
660   if (!tp_strdiff (tp_contact_get_identifier (contact), "me@test.com"))
661     contact = g_ptr_array_index (contacts, 1);
662   g_assert_cmpstr (tp_contact_get_identifier (contact), ==, id);
663   g_assert_cmpstr (tp_contact_get_alias (contact), ==, alias2);
664 }
665 
666 int
main(int argc,char ** argv)667 main (int argc,
668       char **argv)
669 {
670   tp_tests_init (&argc, &argv);
671   g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
672 
673   g_test_add ("/channel/leave/contact/unprepared/no-reason", Test, NULL, setup,
674       test_leave_contact_unprepared_no_reason, teardown);
675   g_test_add ("/channel/leave/contact/unprepared/reason", Test, NULL, setup,
676       test_leave_contact_unprepared_reason, teardown);
677   g_test_add ("/channel/leave/contact/prepared/no-reason", Test, NULL, setup,
678       test_leave_contact_prepared_no_reason, teardown);
679   g_test_add ("/channel/leave/contact/prepared/reason", Test, NULL, setup,
680       test_leave_contact_prepared_reason, teardown);
681 
682   g_test_add ("/channel/leave/room/unprepared/no-reason", Test, NULL, setup,
683       test_leave_room_unprepared_no_reason, teardown);
684   g_test_add ("/channel/leave/room/unprepared/reason", Test, NULL, setup,
685       test_leave_room_unprepared_reason, teardown);
686   g_test_add ("/channel/leave/room/prepared/no-reason", Test, NULL, setup,
687       test_leave_room_prepared_no_reason, teardown);
688   g_test_add ("/channel/leave/room/prepared/reason", Test, NULL, setup,
689       test_leave_room_prepared_reason, teardown);
690 
691   g_test_add ("/channel/close/contact", Test, NULL, setup,
692       test_close, teardown);
693   g_test_add ("/channel/close/room", Test, NULL, setup,
694       test_close_room, teardown);
695 
696   g_test_add ("/channel/destroy", Test, NULL, setup,
697       test_destroy, teardown);
698 
699   g_test_add ("/channel/password/feature", Test, NULL, setup,
700       test_password_feature, teardown);
701   g_test_add ("/channel/password/provide", Test, NULL, setup,
702       test_password_provide, teardown);
703 
704   g_test_add ("/channel/join/room", Test, NULL, setup,
705       test_join_room, teardown);
706 
707   g_test_add ("/channel/contacts", Test, NULL, setup,
708       test_contacts, teardown);
709 
710   return tp_tests_run_with_bus ();
711 }
712