1 /* Tests of TpBaseClient
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 /* We include -internal headers of context to be able to easily access to
13 * their semi-private attributes (connection, account, channels, etc). */
14 #include <telepathy-glib/account-manager.h>
15 #include <telepathy-glib/add-dispatch-operation-context-internal.h>
16 #include <telepathy-glib/base-client.h>
17 #include <telepathy-glib/client.h>
18 #include <telepathy-glib/debug.h>
19 #include <telepathy-glib/defs.h>
20 #include <telepathy-glib/handle-channels-context-internal.h>
21 #include <telepathy-glib/observe-channels-context-internal.h>
22 #include <telepathy-glib/proxy-subclass.h>
23
24 #include "tests/lib/util.h"
25 #include "tests/lib/simple-account.h"
26 #include "tests/lib/simple-channel-dispatch-operation.h"
27 #include "tests/lib/simple-channel-dispatcher.h"
28 #include "tests/lib/simple-channel-request.h"
29 #include "tests/lib/simple-client.h"
30 #include "tests/lib/simple-conn.h"
31 #include "tests/lib/textchan-null.h"
32
33 typedef struct {
34 GMainLoop *mainloop;
35 TpDBusDaemon *dbus;
36
37 /* Service side objects */
38 TpBaseClient *base_client;
39 TpTestsSimpleClient *simple_client;
40 TpBaseConnection *base_connection;
41 TpTestsSimpleAccount *account_service;
42 TpTestsTextChannelNull *text_chan_service;
43 TpTestsTextChannelNull *text_chan_service_2;
44 TpTestsSimpleChannelDispatchOperation *cdo_service;
45 TpTestsSimpleChannelDispatcher *cd_service;
46
47 /* Client side objects */
48 TpAccountManager *account_mgr;
49 TpClient *client;
50 TpConnection *connection;
51 TpAccount *account;
52 TpChannel *text_chan;
53 TpChannel *text_chan_2;
54
55 GError *error /* initialized where needed */;
56 GStrv interfaces;
57 gint wait;
58
59 GPtrArray *delegated;
60 GHashTable *not_delegated;
61 } Test;
62
63 #define ACCOUNT_PATH TP_ACCOUNT_OBJECT_PATH_BASE "what/ev/er"
64 #define CDO_PATH "/whatever"
65
66 static void
setup(Test * test,gconstpointer data)67 setup (Test *test,
68 gconstpointer data)
69 {
70 gchar *chan_path;
71 TpHandle handle;
72 TpHandleRepoIface *contact_repo;
73
74 test->mainloop = g_main_loop_new (NULL, FALSE);
75 test->dbus = tp_tests_dbus_daemon_dup_or_die ();
76
77 test->error = NULL;
78 test->interfaces = NULL;
79
80 /* The case of a non-shared TpAccountManager is tested in
81 * simple-approver.c */
82 test->account_mgr = tp_account_manager_dup ();
83 g_assert (test->account_mgr != NULL);
84
85 /* Claim AccountManager bus-name (needed as we're going to export an Account
86 * object). */
87 tp_dbus_daemon_request_name (test->dbus,
88 TP_ACCOUNT_MANAGER_BUS_NAME, FALSE, &test->error);
89 g_assert_no_error (test->error);
90
91 /* Create service-side Client object */
92 test->simple_client = tp_tests_simple_client_new (test->dbus, "Test", FALSE);
93 g_assert (test->simple_client != NULL);
94 test->base_client = TP_BASE_CLIENT (test->simple_client);
95
96 /* Create service-side Account object */
97 test->account_service = tp_tests_object_new_static_class (
98 TP_TESTS_TYPE_SIMPLE_ACCOUNT, NULL);
99 tp_dbus_daemon_register_object (test->dbus, ACCOUNT_PATH,
100 test->account_service);
101
102 /* Create client-side Client object */
103 test->client = tp_tests_object_new_static_class (TP_TYPE_CLIENT,
104 "dbus-daemon", test->dbus,
105 "bus-name", tp_base_client_get_bus_name (test->base_client),
106 "object-path", tp_base_client_get_object_path (test->base_client),
107 NULL);
108
109 g_assert (test->client != NULL);
110
111 /* Create client-side Account object */
112 test->account = tp_account_manager_ensure_account (test->account_mgr,
113 ACCOUNT_PATH);
114 g_assert (test->account != NULL);
115 g_object_ref (test->account);
116
117 /* Create (service and client sides) connection objects */
118 tp_tests_create_and_connect_conn (TP_TESTS_TYPE_SIMPLE_CONNECTION,
119 "me@test.com", &test->base_connection, &test->connection);
120
121 /* Create service-side text channel object */
122 chan_path = g_strdup_printf ("%s/Channel",
123 tp_proxy_get_object_path (test->connection));
124
125 contact_repo = tp_base_connection_get_handles (test->base_connection,
126 TP_HANDLE_TYPE_CONTACT);
127 g_assert (contact_repo != NULL);
128
129 handle = tp_handle_ensure (contact_repo, "bob", NULL, &test->error);
130 g_assert_no_error (test->error);
131
132 test->text_chan_service = TP_TESTS_TEXT_CHANNEL_NULL (
133 tp_tests_object_new_static_class (
134 TP_TESTS_TYPE_TEXT_CHANNEL_NULL,
135 "connection", test->base_connection,
136 "object-path", chan_path,
137 "handle", handle,
138 NULL));
139
140 /* Create client-side text channel object */
141 test->text_chan = tp_channel_new (test->connection, chan_path, NULL,
142 TP_HANDLE_TYPE_CONTACT, handle, &test->error);
143 g_assert_no_error (test->error);
144
145 tp_handle_unref (contact_repo, handle);
146 g_free (chan_path);
147
148 /* Create a second channel */
149 chan_path = g_strdup_printf ("%s/Channel2",
150 tp_proxy_get_object_path (test->connection));
151
152 handle = tp_handle_ensure (contact_repo, "alice", NULL, &test->error);
153 g_assert_no_error (test->error);
154
155 test->text_chan_service_2 = TP_TESTS_TEXT_CHANNEL_NULL (
156 tp_tests_object_new_static_class (
157 TP_TESTS_TYPE_TEXT_CHANNEL_NULL,
158 "connection", test->base_connection,
159 "object-path", chan_path,
160 "handle", handle,
161 NULL));
162
163 /* Create client-side text channel object */
164 test->text_chan_2 = tp_channel_new (test->connection, chan_path, NULL,
165 TP_HANDLE_TYPE_CONTACT, handle, &test->error);
166 g_assert_no_error (test->error);
167
168 tp_handle_unref (contact_repo, handle);
169 g_free (chan_path);
170
171 /* Create Service side ChannelDispatchOperation object */
172 test->cdo_service = tp_tests_object_new_static_class (
173 TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCH_OPERATION,
174 NULL);
175 tp_dbus_daemon_register_object (test->dbus, CDO_PATH, test->cdo_service);
176
177 tp_tests_simple_channel_dispatch_operation_set_conn_path (test->cdo_service,
178 tp_proxy_get_object_path (test->connection));
179
180 tp_tests_simple_channel_dispatch_operation_set_account_path (
181 test->cdo_service, tp_proxy_get_object_path (test->account));
182
183 tp_tests_simple_channel_dispatch_operation_add_channel (test->cdo_service,
184 test->text_chan);
185 tp_tests_simple_channel_dispatch_operation_add_channel (test->cdo_service,
186 test->text_chan_2);
187
188 g_assert (tp_dbus_daemon_request_name (test->dbus,
189 TP_CHANNEL_DISPATCHER_BUS_NAME, FALSE, NULL));
190
191 /* Create and register CD */
192 test->cd_service = tp_tests_object_new_static_class (
193 TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCHER,
194 "connection", test->base_connection,
195 NULL);
196
197 tp_dbus_daemon_register_object (test->dbus, TP_CHANNEL_DISPATCHER_OBJECT_PATH,
198 test->cd_service);
199 }
200
201 static void
teardown_channel_invalidated_cb(TpChannel * self,guint domain,gint code,gchar * message,Test * test)202 teardown_channel_invalidated_cb (TpChannel *self,
203 guint domain,
204 gint code,
205 gchar *message,
206 Test *test)
207 {
208 g_main_loop_quit (test->mainloop);
209 }
210
211 static void
teardown_run_close_channel(Test * test,TpChannel * channel)212 teardown_run_close_channel (Test *test, TpChannel *channel)
213 {
214 if (channel != NULL && tp_proxy_get_invalidated (channel) == NULL)
215 {
216 g_signal_connect (channel, "invalidated",
217 G_CALLBACK (teardown_channel_invalidated_cb), test);
218 tp_cli_channel_call_close (channel, -1, NULL, NULL, NULL, NULL);
219 g_main_loop_run (test->mainloop);
220 }
221 }
222
223 static void
teardown(Test * test,gconstpointer data)224 teardown (Test *test,
225 gconstpointer data)
226 {
227 teardown_run_close_channel (test, test->text_chan);
228 teardown_run_close_channel (test, test->text_chan_2);
229
230 g_clear_error (&test->error);
231
232 g_strfreev (test->interfaces);
233
234 g_object_unref (test->account_mgr);
235
236 tp_dbus_daemon_release_name (test->dbus, TP_CHANNEL_DISPATCHER_BUS_NAME,
237 NULL);
238
239 g_object_unref (test->base_client);
240 g_object_unref (test->client);
241
242 tp_dbus_daemon_unregister_object (test->dbus, test->account_service);
243 g_object_unref (test->account_service);
244
245 tp_dbus_daemon_release_name (test->dbus, TP_ACCOUNT_MANAGER_BUS_NAME,
246 &test->error);
247 g_assert_no_error (test->error);
248
249 g_object_unref (test->dbus);
250 test->dbus = NULL;
251 g_main_loop_unref (test->mainloop);
252 test->mainloop = NULL;
253
254 g_object_unref (test->account);
255
256 if (test->text_chan_service != NULL)
257 g_object_unref (test->text_chan_service);
258 g_object_unref (test->text_chan);
259
260 if (test->text_chan_service_2 != NULL)
261 g_object_unref (test->text_chan_service_2);
262 g_object_unref (test->text_chan_2);
263
264 tp_clear_object (&test->cdo_service);
265
266 tp_tests_connection_assert_disconnect_succeeds (test->connection);
267 g_object_unref (test->connection);
268 g_object_unref (test->base_connection);
269
270 tp_clear_object (&test->cd_service);
271
272 tp_clear_pointer (&test->delegated, g_ptr_array_unref);
273 tp_clear_pointer (&test->not_delegated, g_hash_table_unref);
274 }
275
276 /* Test Basis */
277
278 static void
test_basics(Test * test,gconstpointer data G_GNUC_UNUSED)279 test_basics (Test *test,
280 gconstpointer data G_GNUC_UNUSED)
281 {
282 TpAccountManager *account_manager;
283 TpDBusDaemon *dbus;
284 gchar *name;
285 gboolean unique;
286
287 g_object_get (test->base_client,
288 "account-manager", &account_manager,
289 "dbus-daemon", &dbus,
290 "name", &name,
291 "uniquify-name", &unique,
292 NULL);
293
294 g_assert (test->account_mgr == account_manager);
295 g_assert (test->dbus == dbus);
296 g_assert_cmpstr ("Test", ==, name);
297 g_assert (!unique);
298
299 g_assert (test->account_mgr == tp_base_client_get_account_manager (
300 test->base_client));
301 g_assert (test->dbus == tp_base_client_get_dbus_daemon (test->base_client));
302 g_assert_cmpstr ("Test", ==, tp_base_client_get_name (test->base_client));
303 g_assert (!tp_base_client_get_uniquify_name (test->base_client));
304
305 g_object_unref (account_manager);
306 g_object_unref (dbus);
307 g_free (name);
308 }
309
310 /* Test register */
311
312 static void
get_client_prop_cb(TpProxy * proxy,GHashTable * properties,const GError * error,gpointer user_data,GObject * weak_object)313 get_client_prop_cb (TpProxy *proxy,
314 GHashTable *properties,
315 const GError *error,
316 gpointer user_data,
317 GObject *weak_object)
318 {
319 Test *test = user_data;
320
321 if (error != NULL)
322 {
323 test->error = g_error_copy (error);
324 goto out;
325 }
326
327 g_assert_cmpint (g_hash_table_size (properties), == , 1);
328
329 g_strfreev (test->interfaces);
330 test->interfaces = g_strdupv ((GStrv) tp_asv_get_strv (
331 properties, "Interfaces"));
332
333 out:
334 g_main_loop_quit (test->mainloop);
335 }
336
337 static void
test_register(Test * test,gconstpointer data G_GNUC_UNUSED)338 test_register (Test *test,
339 gconstpointer data G_GNUC_UNUSED)
340 {
341 tp_base_client_be_a_handler (test->base_client);
342
343 /* no-op as the client is not registered yet */
344 tp_base_client_unregister (test->base_client);
345
346 /* Client is not registered yet */
347 tp_cli_dbus_properties_call_get_all (test->client, -1,
348 TP_IFACE_CLIENT, get_client_prop_cb, test, NULL, NULL);
349 g_main_loop_run (test->mainloop);
350
351 g_assert_error (test->error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN);
352 g_error_free (test->error);
353 test->error = NULL;
354
355 /* register the client */
356 tp_base_client_register (test->base_client, &test->error);
357 g_assert_no_error (test->error);
358
359 tp_cli_dbus_properties_call_get_all (test->client, -1,
360 TP_IFACE_CLIENT, get_client_prop_cb, test, NULL, NULL);
361 g_main_loop_run (test->mainloop);
362
363 g_assert_no_error (test->error);
364
365 /* unregister the client */
366 tp_base_client_unregister (test->base_client);
367 tp_tests_proxy_run_until_dbus_queue_processed (test->client);
368
369 tp_cli_dbus_properties_call_get_all (test->client, -1,
370 TP_IFACE_CLIENT, get_client_prop_cb, test, NULL, NULL);
371 g_main_loop_run (test->mainloop);
372
373 g_assert_error (test->error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN);
374 g_error_free (test->error);
375 test->error = NULL;
376
377 /* re-register the client */
378 tp_base_client_register (test->base_client, &test->error);
379 g_assert_no_error (test->error);
380
381 tp_cli_dbus_properties_call_get_all (test->client, -1,
382 TP_IFACE_CLIENT, get_client_prop_cb, test, NULL, NULL);
383 g_main_loop_run (test->mainloop);
384
385 g_assert_no_error (test->error);
386 }
387
388 /* Test Observer */
389 static void
check_filters(GPtrArray * filters)390 check_filters (GPtrArray *filters)
391 {
392 GHashTable *filter;
393
394 g_assert (filters != NULL);
395 g_assert_cmpuint (filters->len, ==, 2);
396
397 filter = g_ptr_array_index (filters, 0);
398 g_assert_cmpuint (g_hash_table_size (filter), ==, 1);
399 g_assert_cmpstr (tp_asv_get_string (filter, TP_PROP_CHANNEL_CHANNEL_TYPE), ==,
400 TP_IFACE_CHANNEL_TYPE_TEXT);
401
402 filter = g_ptr_array_index (filters, 1);
403 g_assert_cmpuint (g_hash_table_size (filter), ==, 2);
404 g_assert_cmpstr (tp_asv_get_string (filter, TP_PROP_CHANNEL_CHANNEL_TYPE), ==,
405 TP_IFACE_CHANNEL_TYPE_STREAM_TUBE);
406 g_assert_cmpuint (tp_asv_get_uint32 (filter,
407 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL), ==, TP_HANDLE_TYPE_CONTACT);
408 }
409
410 static void
get_observer_prop_cb(TpProxy * proxy,GHashTable * properties,const GError * error,gpointer user_data,GObject * weak_object)411 get_observer_prop_cb (TpProxy *proxy,
412 GHashTable *properties,
413 const GError *error,
414 gpointer user_data,
415 GObject *weak_object)
416 {
417 Test *test = user_data;
418 GPtrArray *filters;
419 gboolean recover, delay;
420 gboolean valid;
421
422 if (error != NULL)
423 {
424 test->error = g_error_copy (error);
425 goto out;
426 }
427
428 g_assert_cmpint (g_hash_table_size (properties), == , 3);
429
430 filters = tp_asv_get_boxed (properties, "ObserverChannelFilter",
431 TP_ARRAY_TYPE_CHANNEL_CLASS_LIST);
432 check_filters (filters);
433
434 recover = tp_asv_get_boolean (properties, "Recover", &valid);
435 g_assert (valid);
436 g_assert (recover);
437
438 delay = tp_asv_get_boolean (properties, "DelayApprovers", &valid);
439 g_assert (valid);
440 g_assert (delay);
441
442 out:
443 g_main_loop_quit (test->mainloop);
444 }
445
446 static void
no_return_cb(TpClient * proxy,const GError * error,gpointer user_data,GObject * weak_object)447 no_return_cb (TpClient *proxy,
448 const GError *error,
449 gpointer user_data,
450 GObject *weak_object)
451 {
452 Test *test = user_data;
453
454 g_clear_error (&test->error);
455
456 if (error != NULL)
457 {
458 test->error = g_error_copy (error);
459 goto out;
460 }
461
462 out:
463 test->wait--;
464 if (test->wait == 0)
465 g_main_loop_quit (test->mainloop);
466 }
467
468 static void
add_channel_to_ptr_array(GPtrArray * arr,TpChannel * channel)469 add_channel_to_ptr_array (GPtrArray *arr,
470 TpChannel *channel)
471 {
472 GValueArray *tmp;
473
474 g_assert (arr != NULL);
475 g_assert (channel != NULL);
476
477 tmp = tp_value_array_build (2,
478 DBUS_TYPE_G_OBJECT_PATH, tp_proxy_get_object_path (channel),
479 TP_HASH_TYPE_STRING_VARIANT_MAP, tp_channel_borrow_immutable_properties (
480 channel),
481 G_TYPE_INVALID);
482
483 g_ptr_array_add (arr, tmp);
484 }
485
486 static void
free_channel_details(gpointer data,gpointer user_data)487 free_channel_details (gpointer data,
488 gpointer user_data)
489 {
490 g_boxed_free (TP_STRUCT_TYPE_CHANNEL_DETAILS, data);
491 }
492
493 static void
test_observer(Test * test,gconstpointer data G_GNUC_UNUSED)494 test_observer (Test *test,
495 gconstpointer data G_GNUC_UNUSED)
496 {
497 GHashTable *filter;
498 GPtrArray *channels, *requests_satisified;
499 GHashTable *info;
500 TpChannel *chan;
501
502 filter = tp_asv_new (
503 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_TEXT,
504 NULL);
505
506 tp_base_client_add_observer_filter (test->base_client, filter);
507 g_hash_table_unref (filter);
508
509 tp_base_client_take_observer_filter (test->base_client, tp_asv_new (
510 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
511 TP_IFACE_CHANNEL_TYPE_STREAM_TUBE,
512 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
513 TP_HANDLE_TYPE_CONTACT,
514 NULL));
515
516 tp_base_client_set_observer_recover (test->base_client, TRUE);
517 tp_base_client_set_observer_delay_approvers (test->base_client, TRUE);
518
519 tp_base_client_register (test->base_client, &test->error);
520 g_assert_no_error (test->error);
521
522 /* Check Client properties */
523 tp_cli_dbus_properties_call_get_all (test->client, -1,
524 TP_IFACE_CLIENT, get_client_prop_cb, test, NULL, NULL);
525 g_main_loop_run (test->mainloop);
526
527 g_assert_no_error (test->error);
528 g_assert_cmpint (g_strv_length (test->interfaces), ==, 1);
529 g_assert (tp_strv_contains ((const gchar * const *) test->interfaces,
530 TP_IFACE_CLIENT_OBSERVER));
531
532 /* Check Observer properties */
533 tp_cli_dbus_properties_call_get_all (test->client, -1,
534 TP_IFACE_CLIENT_OBSERVER, get_observer_prop_cb, test, NULL, NULL);
535 g_main_loop_run (test->mainloop);
536
537 g_assert_no_error (test->error);
538
539 /* Call ObserveChannels */
540 channels = g_ptr_array_sized_new (1);
541 add_channel_to_ptr_array (channels, test->text_chan);
542
543 requests_satisified = g_ptr_array_sized_new (0);
544 info = tp_asv_new (
545 "recovering", G_TYPE_BOOLEAN, TRUE,
546 NULL);
547
548 tp_proxy_add_interface_by_id (TP_PROXY (test->client),
549 TP_IFACE_QUARK_CLIENT_OBSERVER);
550
551 tp_cli_client_observer_call_observe_channels (test->client, -1,
552 tp_proxy_get_object_path (test->account),
553 tp_proxy_get_object_path (test->connection),
554 channels, "/", requests_satisified, info,
555 no_return_cb, test, NULL, NULL);
556
557 test->wait++;
558 g_main_loop_run (test->mainloop);
559 g_assert_no_error (test->error);
560
561 g_assert (test->simple_client->observe_ctx != NULL);
562 g_assert (tp_observe_channels_context_is_recovering (
563 test->simple_client->observe_ctx));
564
565 g_assert (test->simple_client->observe_ctx->account == test->account);
566
567 /* Now call it with an invalid argument */
568 tp_asv_set_boolean (info, "FAIL", TRUE);
569
570 tp_cli_client_observer_call_observe_channels (test->client, -1,
571 tp_proxy_get_object_path (test->account),
572 tp_proxy_get_object_path (test->connection),
573 channels, "/", requests_satisified, info,
574 no_return_cb, test, NULL, NULL);
575
576 test->wait++;
577 g_main_loop_run (test->mainloop);
578 g_assert_error (test->error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT);
579 g_clear_error (&test->error);
580
581 /* The channel being observed is invalidated while preparing */
582 g_hash_table_remove (info, "FAIL");
583
584 tp_cli_client_observer_call_observe_channels (test->client, -1,
585 tp_proxy_get_object_path (test->account),
586 tp_proxy_get_object_path (test->connection),
587 channels, "/", requests_satisified, info,
588 no_return_cb, test, NULL, NULL);
589
590 tp_tests_text_channel_null_close (test->text_chan_service);
591
592 test->wait++;
593 g_main_loop_run (test->mainloop);
594 g_assert_no_error (test->error);
595
596 chan = g_ptr_array_index (test->simple_client->observe_ctx->channels, 0);
597 g_assert (TP_IS_CHANNEL (chan));
598 g_assert (tp_proxy_get_invalidated (chan) != NULL);
599
600 g_ptr_array_foreach (channels, free_channel_details, NULL);
601 g_ptr_array_unref (channels);
602 g_ptr_array_unref (requests_satisified);
603 g_hash_table_unref (info);
604 }
605
606 /* Test Approver */
607 static void
get_approver_prop_cb(TpProxy * proxy,GHashTable * properties,const GError * error,gpointer user_data,GObject * weak_object)608 get_approver_prop_cb (TpProxy *proxy,
609 GHashTable *properties,
610 const GError *error,
611 gpointer user_data,
612 GObject *weak_object)
613 {
614 Test *test = user_data;
615 GPtrArray *filters;
616
617 if (error != NULL)
618 {
619 test->error = g_error_copy (error);
620 goto out;
621 }
622
623 g_assert_cmpint (g_hash_table_size (properties), == , 1);
624
625 filters = tp_asv_get_boxed (properties, "ApproverChannelFilter",
626 TP_ARRAY_TYPE_CHANNEL_CLASS_LIST);
627 check_filters (filters);
628
629 out:
630 g_main_loop_quit (test->mainloop);
631 }
632
633 static void
test_approver(Test * test,gconstpointer data G_GNUC_UNUSED)634 test_approver (Test *test,
635 gconstpointer data G_GNUC_UNUSED)
636 {
637 GHashTable *filter;
638 GPtrArray *channels, *chans;
639 GHashTable *properties;
640 static const char *interfaces[] = { NULL };
641 static const gchar *possible_handlers[] = {
642 TP_CLIENT_BUS_NAME_BASE ".Badger", NULL, };
643 guint i;
644
645 filter = tp_asv_new (
646 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_TEXT,
647 NULL);
648
649 tp_base_client_add_approver_filter (test->base_client, filter);
650 g_hash_table_unref (filter);
651
652 tp_base_client_take_approver_filter (test->base_client, tp_asv_new (
653 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
654 TP_IFACE_CHANNEL_TYPE_STREAM_TUBE,
655 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
656 TP_HANDLE_TYPE_CONTACT,
657 NULL));
658
659 tp_base_client_register (test->base_client, &test->error);
660 g_assert_no_error (test->error);
661
662 /* Check Client properties */
663 tp_cli_dbus_properties_call_get_all (test->client, -1,
664 TP_IFACE_CLIENT, get_client_prop_cb, test, NULL, NULL);
665 g_main_loop_run (test->mainloop);
666
667 g_assert_no_error (test->error);
668 g_assert_cmpint (g_strv_length (test->interfaces), ==, 1);
669 g_assert (tp_strv_contains ((const gchar * const *) test->interfaces,
670 TP_IFACE_CLIENT_APPROVER));
671
672 /* Check Approver properties */
673 tp_cli_dbus_properties_call_get_all (test->client, -1,
674 TP_IFACE_CLIENT_APPROVER, get_approver_prop_cb, test, NULL, NULL);
675 g_main_loop_run (test->mainloop);
676 g_assert_no_error (test->error);
677
678 /* Call AddDispatchOperation */
679 channels = g_ptr_array_sized_new (2);
680 add_channel_to_ptr_array (channels, test->text_chan);
681 add_channel_to_ptr_array (channels, test->text_chan_2);
682
683 properties = tp_asv_new (
684 TP_PROP_CHANNEL_DISPATCH_OPERATION_INTERFACES,
685 G_TYPE_STRV, interfaces,
686 TP_PROP_CHANNEL_DISPATCH_OPERATION_CONNECTION,
687 DBUS_TYPE_G_OBJECT_PATH, tp_proxy_get_object_path (test->connection),
688 TP_PROP_CHANNEL_DISPATCH_OPERATION_ACCOUNT,
689 DBUS_TYPE_G_OBJECT_PATH, tp_proxy_get_object_path (test->account),
690 TP_PROP_CHANNEL_DISPATCH_OPERATION_POSSIBLE_HANDLERS,
691 G_TYPE_STRV, possible_handlers,
692 NULL);
693
694 tp_proxy_add_interface_by_id (TP_PROXY (test->client),
695 TP_IFACE_QUARK_CLIENT_APPROVER);
696
697 tp_cli_client_approver_call_add_dispatch_operation (test->client, -1,
698 channels, CDO_PATH, properties,
699 no_return_cb, test, NULL, NULL);
700
701 test->wait++;
702 g_main_loop_run (test->mainloop);
703 g_assert_no_error (test->error);
704
705 g_assert (test->simple_client->add_dispatch_ctx != NULL);
706 chans = tp_channel_dispatch_operation_borrow_channels (
707 test->simple_client->add_dispatch_ctx->dispatch_operation);
708 g_assert_cmpuint (chans->len, ==, 2);
709
710 /* Check that we reuse existing proxies rather than creating new ones */
711 g_assert (test->simple_client->add_dispatch_ctx->account == test->account);
712 g_assert (tp_channel_dispatch_operation_borrow_account (
713 test->simple_client->add_dispatch_ctx->dispatch_operation) ==
714 test->account);
715
716 g_assert (tp_channel_dispatch_operation_borrow_connection (
717 test->simple_client->add_dispatch_ctx->dispatch_operation) ==
718 test->simple_client->add_dispatch_ctx->connection);
719
720 g_assert (chans->len == test->simple_client->add_dispatch_ctx->channels->len);
721 for (i = 0; i < chans->len; i++)
722 {
723 g_assert (g_ptr_array_index (chans, i) ==
724 g_ptr_array_index (test->simple_client->add_dispatch_ctx->channels,
725 i));
726 }
727
728 /* Another call to AddDispatchOperation, the second channel will be
729 * invalidated during the call */
730 tp_cli_client_approver_call_add_dispatch_operation (test->client, -1,
731 channels, CDO_PATH, properties,
732 no_return_cb, test, NULL, NULL);
733
734 tp_tests_text_channel_null_close (test->text_chan_service_2);
735
736 test->wait++;
737 g_object_unref (test->text_chan_service_2);
738 test->text_chan_service_2 = NULL;
739
740 tp_tests_simple_channel_dispatch_operation_lost_channel (test->cdo_service,
741 test->text_chan_2);
742
743 g_main_loop_run (test->mainloop);
744 g_assert_no_error (test->error);
745
746 g_assert (test->simple_client->add_dispatch_ctx != NULL);
747 /* The CDO only contain valid channels */
748 chans = tp_channel_dispatch_operation_borrow_channels (
749 test->simple_client->add_dispatch_ctx->dispatch_operation);
750 g_assert_cmpuint (chans->len, ==, 1);
751 /* But the context contains both */
752 g_assert_cmpuint (test->simple_client->add_dispatch_ctx->channels->len,
753 ==, 2);
754
755 /* Another call to AddDispatchOperation, the last channel will be
756 * invalidated during the call */
757 tp_cli_client_approver_call_add_dispatch_operation (test->client, -1,
758 channels, CDO_PATH, properties,
759 no_return_cb, test, NULL, NULL);
760
761 tp_tests_text_channel_null_close (test->text_chan_service);
762 g_object_unref (test->text_chan_service);
763 test->text_chan_service = NULL;
764
765 tp_tests_simple_channel_dispatch_operation_lost_channel (test->cdo_service,
766 test->text_chan);
767
768 test->wait++;
769 g_main_loop_run (test->mainloop);
770 g_assert_no_error (test->error);
771
772 g_ptr_array_foreach (channels, free_channel_details, NULL);
773 g_ptr_array_unref (channels);
774 g_hash_table_unref (properties);
775 }
776
777 /* Test Handler */
778 static void
get_handler_prop_cb(TpProxy * proxy,GHashTable * properties,const GError * error,gpointer user_data,GObject * weak_object)779 get_handler_prop_cb (TpProxy *proxy,
780 GHashTable *properties,
781 const GError *error,
782 gpointer user_data,
783 GObject *weak_object)
784 {
785 Test *test = user_data;
786 GPtrArray *filters;
787 gboolean bypass;
788 gboolean valid;
789 const gchar * const * capabilities;
790 GPtrArray *handled;
791
792 if (error != NULL)
793 {
794 test->error = g_error_copy (error);
795 goto out;
796 }
797
798 g_assert_cmpint (g_hash_table_size (properties), == , 4);
799
800 filters = tp_asv_get_boxed (properties, "HandlerChannelFilter",
801 TP_ARRAY_TYPE_CHANNEL_CLASS_LIST);
802 check_filters (filters);
803
804 bypass = tp_asv_get_boolean (properties, "BypassApproval", &valid);
805 g_assert (valid);
806 g_assert (bypass);
807
808 capabilities = tp_asv_get_strv (properties, "Capabilities");
809 g_assert_cmpint (g_strv_length ((GStrv) capabilities), ==, 5);
810 g_assert (tp_strv_contains (capabilities, "badger"));
811 g_assert (tp_strv_contains (capabilities, "mushroom"));
812 g_assert (tp_strv_contains (capabilities, "snake"));
813 g_assert (tp_strv_contains (capabilities, "goat"));
814 g_assert (tp_strv_contains (capabilities, "pony"));
815
816 handled = tp_asv_get_boxed (properties, "HandledChannels",
817 TP_ARRAY_TYPE_OBJECT_PATH_LIST);
818 g_assert (handled != NULL);
819 g_assert_cmpint (handled->len, ==, 0);
820
821 out:
822 g_main_loop_quit (test->mainloop);
823 }
824
825 static void
channel_invalidated_cb(TpChannel * channel,guint domain,gint code,gchar * message,Test * test)826 channel_invalidated_cb (TpChannel *channel,
827 guint domain,
828 gint code,
829 gchar *message,
830 Test *test)
831 {
832 g_main_loop_quit (test->mainloop);
833 }
834
835 static void
test_handler(Test * test,gconstpointer data G_GNUC_UNUSED)836 test_handler (Test *test,
837 gconstpointer data G_GNUC_UNUSED)
838 {
839 GHashTable *filter;
840 const gchar *caps[] = { "mushroom", "snake", NULL };
841 GPtrArray *channels;
842 GPtrArray *requests_satisified;
843 GHashTable *info;
844 GList *chans;
845 TpTestsSimpleClient *client_2;
846
847 filter = tp_asv_new (
848 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_TEXT,
849 NULL);
850
851 tp_base_client_add_handler_filter (test->base_client, filter);
852 g_hash_table_unref (filter);
853
854 tp_base_client_take_handler_filter (test->base_client, tp_asv_new (
855 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
856 TP_IFACE_CHANNEL_TYPE_STREAM_TUBE,
857 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
858 TP_HANDLE_TYPE_CONTACT,
859 NULL));
860
861 tp_base_client_set_handler_bypass_approval (test->base_client, TRUE);
862
863 tp_base_client_add_handler_capability (test->base_client, "badger");
864 tp_base_client_add_handler_capabilities (test->base_client, caps);
865 tp_base_client_add_handler_capabilities_varargs (test->base_client,
866 "goat", "pony", NULL);
867
868 tp_base_client_register (test->base_client, &test->error);
869 g_assert_no_error (test->error);
870
871 /* Check Client properties */
872 tp_cli_dbus_properties_call_get_all (test->client, -1,
873 TP_IFACE_CLIENT, get_client_prop_cb, test, NULL, NULL);
874 g_main_loop_run (test->mainloop);
875
876 g_assert_no_error (test->error);
877 g_assert_cmpint (g_strv_length (test->interfaces), ==, 1);
878 g_assert (tp_strv_contains ((const gchar * const *) test->interfaces,
879 TP_IFACE_CLIENT_HANDLER));
880
881 /* Check Handler properties */
882 tp_cli_dbus_properties_call_get_all (test->client, -1,
883 TP_IFACE_CLIENT_HANDLER, get_handler_prop_cb, test, NULL, NULL);
884 g_main_loop_run (test->mainloop);
885 g_assert_no_error (test->error);
886
887 g_assert (!tp_base_client_is_handling_channel (test->base_client,
888 test->text_chan));
889 g_assert (!tp_base_client_is_handling_channel (test->base_client,
890 test->text_chan_2));
891
892 /* Call HandleChannels */
893 channels = g_ptr_array_sized_new (2);
894 add_channel_to_ptr_array (channels, test->text_chan);
895 add_channel_to_ptr_array (channels, test->text_chan_2);
896
897 requests_satisified = g_ptr_array_sized_new (0);
898 info = g_hash_table_new (NULL, NULL);
899
900 tp_proxy_add_interface_by_id (TP_PROXY (test->client),
901 TP_IFACE_QUARK_CLIENT_HANDLER);
902
903 tp_cli_client_handler_call_handle_channels (test->client, -1,
904 tp_proxy_get_object_path (test->account),
905 tp_proxy_get_object_path (test->connection),
906 channels, requests_satisified, 0, info,
907 no_return_cb, test, NULL, NULL);
908
909 test->wait++;
910 g_main_loop_run (test->mainloop);
911 g_assert_no_error (test->error);
912
913 g_assert (test->simple_client->handle_channels_ctx != NULL);
914 g_assert (test->simple_client->handle_channels_ctx->account == test->account);
915
916 chans = tp_base_client_get_handled_channels (test->base_client);
917 g_assert_cmpuint (g_list_length (chans), ==, 2);
918 g_list_free (chans);
919
920 g_assert (tp_base_client_is_handling_channel (test->base_client,
921 test->text_chan));
922 g_assert (tp_base_client_is_handling_channel (test->base_client,
923 test->text_chan_2));
924
925 /* One of the channel is closed */
926 g_signal_connect (test->text_chan, "invalidated",
927 G_CALLBACK (channel_invalidated_cb), test);
928 tp_tests_text_channel_null_close (test->text_chan_service);
929 g_main_loop_run (test->mainloop);
930
931 chans = tp_base_client_get_handled_channels (test->base_client);
932 g_assert_cmpuint (g_list_length (chans), ==, 1);
933 g_list_free (chans);
934
935 g_assert (!tp_base_client_is_handling_channel (test->base_client,
936 test->text_chan));
937 g_assert (tp_base_client_is_handling_channel (test->base_client,
938 test->text_chan_2));
939
940 /* Create another client sharing the same unique name */
941 client_2 = tp_tests_simple_client_new (test->dbus, "Test", TRUE);
942 tp_base_client_be_a_handler (TP_BASE_CLIENT (client_2));
943 tp_base_client_register (TP_BASE_CLIENT (client_2), &test->error);
944 g_assert_no_error (test->error);
945
946 chans = tp_base_client_get_handled_channels (TP_BASE_CLIENT (client_2));
947 g_assert_cmpuint (g_list_length (chans), ==, 1);
948 g_list_free (chans);
949
950 g_assert (!tp_base_client_is_handling_channel (TP_BASE_CLIENT (client_2),
951 test->text_chan));
952 g_assert (tp_base_client_is_handling_channel (TP_BASE_CLIENT (client_2),
953 test->text_chan_2));
954
955 g_object_unref (client_2);
956
957 g_ptr_array_foreach (channels, free_channel_details, NULL);
958 g_ptr_array_unref (channels);
959 g_ptr_array_unref (requests_satisified);
960 g_hash_table_unref (info);
961 }
962
963 /* Test Requests interface on Handler */
964 static void
get_requests_prop_cb(TpProxy * proxy,GHashTable * properties,const GError * error,gpointer user_data,GObject * weak_object)965 get_requests_prop_cb (TpProxy *proxy,
966 GHashTable *properties,
967 const GError *error,
968 gpointer user_data,
969 GObject *weak_object)
970 {
971 Test *test = user_data;
972
973 if (error != NULL)
974 {
975 test->error = g_error_copy (error);
976 goto out;
977 }
978
979 g_assert_cmpint (g_hash_table_size (properties), == , 0);
980
981 out:
982 g_main_loop_quit (test->mainloop);
983 }
984
985 static void
request_added_cb(TpBaseClient * client,TpAccount * account,TpChannelRequest * request,Test * test)986 request_added_cb (TpBaseClient *client,
987 TpAccount *account,
988 TpChannelRequest *request,
989 Test *test)
990 {
991 GList *requests;
992
993 g_assert (TP_IS_CHANNEL_REQUEST (request));
994 g_assert (TP_IS_ACCOUNT (account));
995 g_assert (tp_proxy_is_prepared (account, TP_ACCOUNT_FEATURE_CORE));
996
997 requests = tp_base_client_get_pending_requests (test->base_client);
998 g_assert_cmpuint (g_list_length ((GList *) requests), ==, 1);
999 g_assert (requests->data == request);
1000 g_list_free (requests);
1001
1002 test->wait--;
1003 if (test->wait == 0)
1004 g_main_loop_quit (test->mainloop);
1005 }
1006
1007 static void
request_removed_cb(TpBaseClient * client,TpChannelRequest * request,const gchar * error,const gchar * reason,Test * test)1008 request_removed_cb (TpBaseClient *client,
1009 TpChannelRequest *request,
1010 const gchar *error,
1011 const gchar *reason,
1012 Test *test)
1013 {
1014 g_assert (TP_IS_CHANNEL_REQUEST (request));
1015
1016 test->wait--;
1017 if (test->wait == 0)
1018 g_main_loop_quit (test->mainloop);
1019 }
1020
1021 static void
test_handler_requests(Test * test,gconstpointer data G_GNUC_UNUSED)1022 test_handler_requests (Test *test,
1023 gconstpointer data G_GNUC_UNUSED)
1024 {
1025 GHashTable *properties;
1026 GPtrArray *channels;
1027 GPtrArray *requests_satisified;
1028 GHashTable *info;
1029 TpChannelRequest *request;
1030 GList *requests;
1031
1032 tp_base_client_take_handler_filter (test->base_client, tp_asv_new (
1033 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
1034 TP_IFACE_CHANNEL_TYPE_STREAM_TUBE,
1035 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
1036 TP_HANDLE_TYPE_CONTACT,
1037 NULL));
1038
1039 tp_base_client_set_handler_request_notification (test->base_client);
1040
1041 tp_base_client_register (test->base_client, &test->error);
1042 g_assert_no_error (test->error);
1043
1044 /* Check Client properties */
1045 tp_cli_dbus_properties_call_get_all (test->client, -1,
1046 TP_IFACE_CLIENT, get_client_prop_cb, test, NULL, NULL);
1047 g_main_loop_run (test->mainloop);
1048
1049 g_assert_no_error (test->error);
1050 g_assert_cmpint (g_strv_length (test->interfaces), ==, 2);
1051 g_assert (tp_strv_contains ((const gchar * const *) test->interfaces,
1052 TP_IFACE_CLIENT_HANDLER));
1053 g_assert (tp_strv_contains ((const gchar * const *) test->interfaces,
1054 TP_IFACE_CLIENT_INTERFACE_REQUESTS));
1055
1056 /* Check Requests properties */
1057 tp_cli_dbus_properties_call_get_all (test->client, -1,
1058 TP_IFACE_CLIENT_INTERFACE_REQUESTS, get_requests_prop_cb,
1059 test, NULL, NULL);
1060 g_main_loop_run (test->mainloop);
1061 g_assert_no_error (test->error);
1062
1063 g_assert (tp_base_client_get_pending_requests (test->base_client) == NULL);
1064
1065 /* Call AddRequest */
1066 properties = tp_asv_new (
1067 TP_PROP_CHANNEL_REQUEST_ACCOUNT, DBUS_TYPE_G_OBJECT_PATH, ACCOUNT_PATH,
1068 NULL);
1069
1070 tp_proxy_add_interface_by_id (TP_PROXY (test->client),
1071 TP_IFACE_QUARK_CLIENT_INTERFACE_REQUESTS);
1072
1073 g_signal_connect (test->base_client, "request-added",
1074 G_CALLBACK (request_added_cb), test);
1075
1076 tp_cli_client_interface_requests_call_add_request (test->client, -1,
1077 "/Request", properties,
1078 no_return_cb, test, NULL, NULL);
1079
1080 test->wait = 2;
1081 g_main_loop_run (test->mainloop);
1082 g_assert_no_error (test->error);
1083
1084 requests = tp_base_client_get_pending_requests (test->base_client);
1085 g_assert (requests != NULL);
1086 g_list_free (requests);
1087
1088 /* Call HandleChannels */
1089 channels = g_ptr_array_sized_new (2);
1090 add_channel_to_ptr_array (channels, test->text_chan);
1091
1092 requests_satisified = g_ptr_array_sized_new (1);
1093 g_ptr_array_add (requests_satisified, "/Request");
1094
1095 info = g_hash_table_new (NULL, NULL);
1096
1097 tp_proxy_add_interface_by_id (TP_PROXY (test->client),
1098 TP_IFACE_QUARK_CLIENT_HANDLER);
1099
1100 tp_cli_client_handler_call_handle_channels (test->client, -1,
1101 tp_proxy_get_object_path (test->account),
1102 tp_proxy_get_object_path (test->connection),
1103 channels, requests_satisified, 0, info,
1104 no_return_cb, test, NULL, NULL);
1105
1106 test->wait++;
1107 g_main_loop_run (test->mainloop);
1108 g_assert_no_error (test->error);
1109
1110 g_assert (test->simple_client->handle_channels_ctx != NULL);
1111 g_assert_cmpint (
1112 test->simple_client->handle_channels_ctx->requests_satisfied->len, ==, 1);
1113 request = g_ptr_array_index (
1114 test->simple_client->handle_channels_ctx->requests_satisfied, 0);
1115 requests = tp_base_client_get_pending_requests (test->base_client);
1116 g_assert (requests->data == request);
1117 g_list_free (requests);
1118
1119 /* Call RemoveRequest */
1120 g_signal_connect (test->base_client, "request-removed",
1121 G_CALLBACK (request_removed_cb), test);
1122
1123 tp_cli_client_interface_requests_call_remove_request (test->client, -1,
1124 "/Request", "Badger", "snake",
1125 no_return_cb, test, NULL, NULL);
1126
1127 test->wait = 2;
1128 g_main_loop_run (test->mainloop);
1129 g_assert_no_error (test->error);
1130
1131 g_assert (tp_base_client_get_pending_requests (test->base_client) == NULL);
1132
1133 g_hash_table_unref (properties);
1134 g_ptr_array_foreach (channels, free_channel_details, NULL);
1135 g_ptr_array_unref (channels);
1136 g_ptr_array_unref (requests_satisified);
1137 g_hash_table_unref (info);
1138 }
1139
1140 static void
claim_with_cb(GObject * source,GAsyncResult * result,gpointer user_data)1141 claim_with_cb (GObject *source,
1142 GAsyncResult *result,
1143 gpointer user_data)
1144 {
1145 Test *test = user_data;
1146
1147 tp_channel_dispatch_operation_claim_with_finish (
1148 TP_CHANNEL_DISPATCH_OPERATION (source), result, &test->error);
1149
1150 test->wait--;
1151 if (test->wait == 0)
1152 g_main_loop_quit (test->mainloop);
1153 }
1154
1155 static void
cdo_finished_cb(TpTestsSimpleChannelDispatchOperation * cdo,Test * test)1156 cdo_finished_cb (TpTestsSimpleChannelDispatchOperation *cdo,
1157 Test *test)
1158 {
1159 tp_clear_object (&test->cdo_service);
1160 }
1161
1162 static void
test_channel_dispatch_operation_claim_with_async(Test * test,gconstpointer data G_GNUC_UNUSED)1163 test_channel_dispatch_operation_claim_with_async (Test *test,
1164 gconstpointer data G_GNUC_UNUSED)
1165 {
1166 GPtrArray *channels;
1167 GHashTable *properties;
1168 static const char *interfaces[] = { NULL };
1169 static const gchar *possible_handlers[] = {
1170 TP_CLIENT_BUS_NAME_BASE ".Badger", NULL, };
1171 TpChannelDispatchOperation *cdo;
1172 GList *handled;
1173
1174 /* Register an Approver and Handler */
1175 tp_base_client_take_approver_filter (test->base_client, tp_asv_new (
1176 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
1177 TP_IFACE_CHANNEL_TYPE_TEXT,
1178 NULL));
1179
1180 tp_base_client_take_handler_filter (test->base_client, tp_asv_new (
1181 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
1182 TP_IFACE_CHANNEL_TYPE_TEXT,
1183 NULL));
1184
1185 tp_base_client_register (test->base_client, &test->error);
1186 g_assert_no_error (test->error);
1187
1188 /* Call AddDispatchOperation */
1189 channels = g_ptr_array_sized_new (2);
1190 add_channel_to_ptr_array (channels, test->text_chan);
1191 add_channel_to_ptr_array (channels, test->text_chan_2);
1192
1193 properties = tp_asv_new (
1194 TP_PROP_CHANNEL_DISPATCH_OPERATION_INTERFACES,
1195 G_TYPE_STRV, interfaces,
1196 TP_PROP_CHANNEL_DISPATCH_OPERATION_CONNECTION,
1197 DBUS_TYPE_G_OBJECT_PATH, tp_proxy_get_object_path (test->connection),
1198 TP_PROP_CHANNEL_DISPATCH_OPERATION_ACCOUNT,
1199 DBUS_TYPE_G_OBJECT_PATH, tp_proxy_get_object_path (test->account),
1200 TP_PROP_CHANNEL_DISPATCH_OPERATION_POSSIBLE_HANDLERS,
1201 G_TYPE_STRV, possible_handlers,
1202 NULL);
1203
1204 tp_proxy_add_interface_by_id (TP_PROXY (test->client),
1205 TP_IFACE_QUARK_CLIENT_APPROVER);
1206
1207 tp_cli_client_approver_call_add_dispatch_operation (test->client, -1,
1208 channels, CDO_PATH, properties,
1209 no_return_cb, test, NULL, NULL);
1210
1211 test->wait++;
1212 g_main_loop_run (test->mainloop);
1213 g_assert_no_error (test->error);
1214
1215 cdo = test->simple_client->add_dispatch_ctx->dispatch_operation;
1216 g_assert (TP_IS_CHANNEL_DISPATCH_OPERATION (cdo));
1217
1218 handled = tp_base_client_get_handled_channels (test->base_client);
1219 g_assert (handled == NULL);
1220
1221 /* Connect to CDO's Finished signal so we can remove it from the bus when
1222 * it's claimed as MC would do. */
1223 g_signal_connect (test->cdo_service, "finished",
1224 G_CALLBACK (cdo_finished_cb), test);
1225
1226 /* Claim the CDO, as the client is also a Handler, it is now handling the
1227 * channels */
1228 tp_channel_dispatch_operation_claim_with_async (cdo, test->base_client,
1229 claim_with_cb, test);
1230
1231 test->wait++;
1232 g_main_loop_run (test->mainloop);
1233 g_assert_no_error (test->error);
1234
1235 handled = tp_base_client_get_handled_channels (test->base_client);
1236 g_assert_cmpuint (g_list_length (handled), ==, 2);
1237 g_list_free (handled);
1238
1239 g_assert (tp_base_client_is_handling_channel (test->base_client,
1240 test->text_chan));
1241 g_assert (tp_base_client_is_handling_channel (test->base_client,
1242 test->text_chan_2));
1243
1244 g_ptr_array_foreach (channels, free_channel_details, NULL);
1245 g_ptr_array_unref (channels);
1246 g_hash_table_unref (properties);
1247 }
1248
1249 static void
delegate_channels_cb(GObject * source,GAsyncResult * result,gpointer user_data)1250 delegate_channels_cb (GObject *source,
1251 GAsyncResult *result,
1252 gpointer user_data)
1253 {
1254 Test *test = user_data;
1255
1256 tp_base_client_delegate_channels_finish (
1257 TP_BASE_CLIENT (source), result, &test->delegated, &test->not_delegated,
1258 &test->error);
1259
1260 test->wait--;
1261 if (test->wait == 0)
1262 g_main_loop_quit (test->mainloop);
1263 }
1264
1265 static void
test_delegate_channels(Test * test,gconstpointer data G_GNUC_UNUSED)1266 test_delegate_channels (Test *test,
1267 gconstpointer data G_GNUC_UNUSED)
1268 {
1269 GPtrArray *channels;
1270 GPtrArray *requests_satisified;
1271 GHashTable *info;
1272 GList *chans;
1273 GError *error = NULL;
1274
1275 tp_base_client_be_a_handler (test->base_client);
1276
1277 tp_base_client_register (test->base_client, &test->error);
1278 g_assert_no_error (test->error);
1279
1280 /* Call HandleChannels */
1281 channels = g_ptr_array_sized_new (2);
1282 add_channel_to_ptr_array (channels, test->text_chan);
1283 add_channel_to_ptr_array (channels, test->text_chan_2);
1284
1285 requests_satisified = g_ptr_array_sized_new (0);
1286 info = g_hash_table_new (NULL, NULL);
1287
1288 tp_proxy_add_interface_by_id (TP_PROXY (test->client),
1289 TP_IFACE_QUARK_CLIENT_HANDLER);
1290
1291 tp_cli_client_handler_call_handle_channels (test->client, -1,
1292 tp_proxy_get_object_path (test->account),
1293 tp_proxy_get_object_path (test->connection),
1294 channels, requests_satisified, 0, info,
1295 no_return_cb, test, NULL, NULL);
1296
1297 test->wait++;
1298 g_main_loop_run (test->mainloop);
1299 g_assert_no_error (test->error);
1300
1301 /* The client is handling the 2 channels */
1302 chans = tp_base_client_get_handled_channels (test->base_client);
1303 g_assert_cmpuint (g_list_length (chans), ==, 2);
1304 g_list_free (chans);
1305
1306 g_assert (tp_base_client_is_handling_channel (test->base_client,
1307 test->text_chan));
1308 g_assert (tp_base_client_is_handling_channel (test->base_client,
1309 test->text_chan_2));
1310
1311 /* Try to delegate the first one */
1312 chans = g_list_append (NULL, test->text_chan);
1313
1314 tp_base_client_delegate_channels_async (test->base_client,
1315 chans, TP_USER_ACTION_TIME_CURRENT_TIME, NULL,
1316 delegate_channels_cb, test);
1317
1318 g_list_free (chans);
1319
1320 test->wait++;
1321 g_main_loop_run (test->mainloop);
1322 g_assert_no_error (test->error);
1323
1324 g_assert_cmpuint (test->delegated->len, ==, 1);
1325 g_assert (g_ptr_array_index (test->delegated, 0) == test->text_chan);
1326 g_assert_cmpuint (g_hash_table_size (test->not_delegated), ==, 0);
1327
1328 /* Client is not handling the channel any more */
1329 chans = tp_base_client_get_handled_channels (test->base_client);
1330 g_assert_cmpuint (g_list_length (chans), ==, 1);
1331 g_list_free (chans);
1332
1333 g_assert (!tp_base_client_is_handling_channel (test->base_client,
1334 test->text_chan));
1335 g_assert (tp_base_client_is_handling_channel (test->base_client,
1336 test->text_chan_2));
1337
1338 /* Try delegating the second channel, but MC refuses */
1339 test->cd_service->refuse_delegate = TRUE;
1340
1341 chans = g_list_append (NULL, test->text_chan_2);
1342
1343 tp_base_client_delegate_channels_async (test->base_client,
1344 chans, TP_USER_ACTION_TIME_CURRENT_TIME, NULL,
1345 delegate_channels_cb, test);
1346
1347 g_list_free (chans);
1348
1349 test->wait++;
1350 g_main_loop_run (test->mainloop);
1351 g_assert_no_error (test->error);
1352
1353 g_assert_cmpuint (test->delegated->len, ==, 0);
1354 g_assert_cmpuint (g_hash_table_size (test->not_delegated), ==, 1);
1355 error = g_hash_table_lookup (test->not_delegated, test->text_chan_2);
1356 g_assert_error (error, TP_ERROR, TP_ERROR_BUSY);
1357
1358 /* Client is still handling the channel */
1359 chans = tp_base_client_get_handled_channels (test->base_client);
1360 g_assert_cmpuint (g_list_length (chans), ==, 1);
1361 g_list_free (chans);
1362
1363 g_assert (!tp_base_client_is_handling_channel (test->base_client,
1364 test->text_chan));
1365 g_assert (tp_base_client_is_handling_channel (test->base_client,
1366 test->text_chan_2));
1367
1368 g_ptr_array_foreach (channels, free_channel_details, NULL);
1369 g_ptr_array_unref (channels);
1370 g_ptr_array_unref (requests_satisified);
1371 g_hash_table_unref (info);
1372 }
1373
1374 static void
present_channel_cb(GObject * source,GAsyncResult * result,gpointer user_data)1375 present_channel_cb (GObject *source,
1376 GAsyncResult *result,
1377 gpointer user_data)
1378 {
1379 Test *test = user_data;
1380
1381 tp_channel_dispatcher_present_channel_finish (
1382 TP_CHANNEL_DISPATCHER (source), result, &test->error);
1383
1384 test->wait--;
1385 if (test->wait == 0)
1386 g_main_loop_quit (test->mainloop);
1387 }
1388
1389 static void
test_present_channel(Test * test,gconstpointer data G_GNUC_UNUSED)1390 test_present_channel (Test *test,
1391 gconstpointer data G_GNUC_UNUSED)
1392 {
1393 TpChannelDispatcher *cd;
1394
1395 cd = tp_channel_dispatcher_new (test->dbus);
1396
1397 tp_channel_dispatcher_present_channel_async (cd, test->text_chan,
1398 TP_USER_ACTION_TIME_CURRENT_TIME, present_channel_cb, test);
1399
1400 test->wait++;
1401 g_main_loop_run (test->mainloop);
1402 g_assert_no_error (test->error);
1403
1404 g_object_unref (cd);
1405 }
1406
1407 #define PREFERRED_HANDLER_NAME TP_CLIENT_BUS_NAME_BASE ".Badger"
1408
1409 static gboolean
channel_in_array(GPtrArray * array,TpChannel * channel)1410 channel_in_array (GPtrArray *array,
1411 TpChannel *channel)
1412 {
1413 guint i;
1414
1415 for (i = 0; i < array->len; i++)
1416 {
1417 TpChannel *c = g_ptr_array_index (array, i);
1418
1419 if (!tp_strdiff (tp_proxy_get_object_path (channel),
1420 tp_proxy_get_object_path (c)))
1421 return TRUE;
1422 }
1423
1424 return FALSE;
1425 }
1426
1427 static void
delegated_channels_cb(TpBaseClient * client,GPtrArray * channels,gpointer user_data)1428 delegated_channels_cb (TpBaseClient *client,
1429 GPtrArray *channels,
1430 gpointer user_data)
1431 {
1432 Test *test = user_data;
1433
1434 g_assert_cmpuint (channels->len, ==, 2);
1435
1436 g_assert (channel_in_array (channels, test->text_chan));
1437 g_assert (channel_in_array (channels, test->text_chan_2));
1438
1439 test->wait--;
1440 if (test->wait == 0)
1441 g_main_loop_quit (test->mainloop);
1442 }
1443
1444 static void
delegate_to_preferred_handler(Test * test,gboolean supported)1445 delegate_to_preferred_handler (Test *test,
1446 gboolean supported)
1447 {
1448 GPtrArray *channels;
1449 GPtrArray *requests_satisified;
1450 GPtrArray *requests;
1451 GHashTable *request_props;
1452 GHashTable *info;
1453 TpTestsSimpleChannelRequest *cr;
1454 GHashTable *hints;
1455
1456 tp_base_client_be_a_handler (test->base_client);
1457
1458 if (supported)
1459 {
1460 tp_base_client_set_delegated_channels_callback (test->base_client,
1461 delegated_channels_cb, test, NULL);
1462 }
1463
1464 tp_base_client_register (test->base_client, &test->error);
1465 g_assert_no_error (test->error);
1466
1467 /* Call HandleChannels */
1468 channels = g_ptr_array_sized_new (2);
1469 add_channel_to_ptr_array (channels, test->text_chan);
1470 add_channel_to_ptr_array (channels, test->text_chan_2);
1471
1472 requests_satisified = g_ptr_array_sized_new (0);
1473 info = g_hash_table_new (NULL, NULL);
1474
1475 tp_proxy_add_interface_by_id (TP_PROXY (test->client),
1476 TP_IFACE_QUARK_CLIENT_HANDLER);
1477
1478 tp_cli_client_handler_call_handle_channels (test->client, -1,
1479 tp_proxy_get_object_path (test->account),
1480 tp_proxy_get_object_path (test->connection),
1481 channels, requests_satisified, 0, info,
1482 no_return_cb, test, NULL, NULL);
1483
1484 test->wait++;
1485 g_main_loop_run (test->mainloop);
1486 g_assert_no_error (test->error);
1487
1488 /* The client is handling the 2 channels */
1489 g_assert (tp_base_client_is_handling_channel (test->base_client,
1490 test->text_chan));
1491 g_assert (tp_base_client_is_handling_channel (test->base_client,
1492 test->text_chan_2));
1493
1494 /* Another client asks to dispatch the channel to it */
1495 requests = g_ptr_array_new ();
1496
1497 hints = tp_asv_new (
1498 "org.freedesktop.Telepathy.ChannelRequest.DelegateToPreferredHandler",
1499 G_TYPE_BOOLEAN, TRUE,
1500 NULL);
1501
1502 cr = tp_tests_simple_channel_request_new ("/CR",
1503 TP_TESTS_SIMPLE_CONNECTION (test->base_connection), ACCOUNT_PATH,
1504 TP_USER_ACTION_TIME_CURRENT_TIME, PREFERRED_HANDLER_NAME,
1505 requests, hints);
1506
1507 g_ptr_array_add (requests_satisified, "/CR");
1508
1509 request_props = g_hash_table_new_full (g_str_hash, g_str_equal,
1510 NULL, (GDestroyNotify) g_hash_table_unref);
1511
1512 g_hash_table_insert (request_props, "/CR",
1513 tp_tests_simple_channel_request_dup_immutable_props (cr));
1514
1515 tp_asv_set_boxed (info,
1516 "request-properties", TP_HASH_TYPE_OBJECT_IMMUTABLE_PROPERTIES_MAP,
1517 request_props);
1518
1519 tp_cli_client_handler_call_handle_channels (test->client, -1,
1520 tp_proxy_get_object_path (test->account),
1521 tp_proxy_get_object_path (test->connection),
1522 channels, requests_satisified, 0, info,
1523 no_return_cb, test, NULL, NULL);
1524
1525 test->wait = 1;
1526
1527 /* If we support the DelegateToPreferredHandler hint, we wait for
1528 * delegated_channels_cb to be called */
1529 if (supported)
1530 test->wait++;
1531
1532 g_main_loop_run (test->mainloop);
1533 g_assert_no_error (test->error);
1534
1535 if (supported)
1536 {
1537 /* We are not handling the channels any more */
1538 g_assert (!tp_base_client_is_handling_channel (test->base_client,
1539 test->text_chan));
1540 g_assert (!tp_base_client_is_handling_channel (test->base_client,
1541 test->text_chan_2));
1542 }
1543 else
1544 {
1545 /* We are still handling the channels */
1546 g_assert (tp_base_client_is_handling_channel (test->base_client,
1547 test->text_chan));
1548 g_assert (tp_base_client_is_handling_channel (test->base_client,
1549 test->text_chan_2));
1550 }
1551
1552 tp_base_client_unregister (test->base_client);
1553
1554 g_object_unref (cr);
1555 g_ptr_array_foreach (channels, free_channel_details, NULL);
1556 g_ptr_array_unref (channels);
1557 g_ptr_array_unref (requests_satisified);
1558 g_ptr_array_unref (requests);
1559 g_hash_table_unref (info);
1560 g_hash_table_unref (hints);
1561 g_hash_table_unref (request_props);
1562 }
1563
1564 static void
test_delegate_to_preferred_handler_not_supported(Test * test,gconstpointer data G_GNUC_UNUSED)1565 test_delegate_to_preferred_handler_not_supported (Test *test,
1566 gconstpointer data G_GNUC_UNUSED)
1567 {
1568 delegate_to_preferred_handler (test, FALSE);
1569 }
1570
1571 static void
test_delegate_to_preferred_handler_supported(Test * test,gconstpointer data G_GNUC_UNUSED)1572 test_delegate_to_preferred_handler_supported (Test *test,
1573 gconstpointer data G_GNUC_UNUSED)
1574 {
1575 delegate_to_preferred_handler (test, TRUE);
1576 }
1577
1578 int
main(int argc,char ** argv)1579 main (int argc,
1580 char **argv)
1581 {
1582 tp_tests_init (&argc, &argv);
1583
1584 g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
1585
1586 g_test_add ("/base-client/basics", Test, NULL, setup, test_basics, teardown);
1587 g_test_add ("/base-client/register", Test, NULL, setup, test_register,
1588 teardown);
1589 g_test_add ("/base-client/observer", Test, NULL, setup, test_observer,
1590 teardown);
1591 g_test_add ("/base-client/approver", Test, NULL, setup, test_approver,
1592 teardown);
1593 g_test_add ("/base-client/handler", Test, NULL, setup, test_handler,
1594 teardown);
1595 g_test_add ("/base-client/handler-requests", Test, NULL, setup,
1596 test_handler_requests, teardown);
1597 g_test_add ("/cdo/claim_with", Test, NULL, setup,
1598 test_channel_dispatch_operation_claim_with_async, teardown);
1599 g_test_add ("/base-client/delegate-channels", Test, NULL, setup,
1600 test_delegate_channels, teardown);
1601 g_test_add ("/cd/present-channel", Test, NULL, setup,
1602 test_present_channel, teardown);
1603 g_test_add ("/cd/delegate-to-preferred-handler/not-supported", Test, NULL,
1604 setup, test_delegate_to_preferred_handler_not_supported, teardown);
1605 g_test_add ("/cd/delegate-to-preferred-handler/supported", Test, NULL,
1606 setup, test_delegate_to_preferred_handler_supported, teardown);
1607
1608 return tp_tests_run_with_bus ();
1609 }
1610