1 /* Tests of TpSimpleHandler
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 <telepathy-glib/simple-handler.h>
13 #include <telepathy-glib/client.h>
14 #include <telepathy-glib/debug.h>
15 #include <telepathy-glib/defs.h>
16 #include <telepathy-glib/proxy-subclass.h>
17
18 #include "tests/lib/util.h"
19 #include "tests/lib/simple-account.h"
20 #include "tests/lib/simple-conn.h"
21 #include "tests/lib/textchan-null.h"
22
23 typedef struct {
24 GMainLoop *mainloop;
25 TpDBusDaemon *dbus;
26
27 /* Service side objects */
28 TpBaseClient *simple_handler;
29 TpBaseConnection *base_connection;
30 TpTestsSimpleAccount *account_service;
31 TpTestsTextChannelNull *text_chan_service;
32
33 /* Client side objects */
34 TpClient *client;
35 TpConnection *connection;
36 TpAccount *account;
37 TpChannel *text_chan;
38
39 GError *error /* initialized where needed */;
40 } Test;
41
42 #define ACCOUNT_PATH TP_ACCOUNT_OBJECT_PATH_BASE "what/ev/er"
43
44 static void
setup(Test * test,gconstpointer data)45 setup (Test *test,
46 gconstpointer data)
47 {
48 gchar *chan_path;
49 TpHandle handle;
50 TpHandleRepoIface *contact_repo;
51
52 test->mainloop = g_main_loop_new (NULL, FALSE);
53 test->dbus = tp_tests_dbus_daemon_dup_or_die ();
54
55 test->error = NULL;
56
57 /* Claim AccountManager bus-name (needed as we're going to export an Account
58 * object). */
59 tp_dbus_daemon_request_name (test->dbus,
60 TP_ACCOUNT_MANAGER_BUS_NAME, FALSE, &test->error);
61 g_assert_no_error (test->error);
62
63 /* Create service-side Account object */
64 test->account_service = tp_tests_object_new_static_class (
65 TP_TESTS_TYPE_SIMPLE_ACCOUNT, NULL);
66 tp_dbus_daemon_register_object (test->dbus, ACCOUNT_PATH,
67 test->account_service);
68
69 /* Create client-side Account object */
70 test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL);
71 g_assert (test->account != NULL);
72
73 /* Create (service and client sides) connection objects */
74 tp_tests_create_and_connect_conn (TP_TESTS_TYPE_SIMPLE_CONNECTION,
75 "me@test.com", &test->base_connection, &test->connection);
76
77 /* Create service-side text channel object */
78 chan_path = g_strdup_printf ("%s/Channel",
79 tp_proxy_get_object_path (test->connection));
80
81 contact_repo = tp_base_connection_get_handles (test->base_connection,
82 TP_HANDLE_TYPE_CONTACT);
83 g_assert (contact_repo != NULL);
84
85 handle = tp_handle_ensure (contact_repo, "bob", NULL, &test->error);
86 g_assert_no_error (test->error);
87
88 test->text_chan_service = TP_TESTS_TEXT_CHANNEL_NULL (
89 tp_tests_object_new_static_class (
90 TP_TESTS_TYPE_TEXT_CHANNEL_NULL,
91 "connection", test->base_connection,
92 "object-path", chan_path,
93 "handle", handle,
94 NULL));
95
96 /* Create client-side text channel object */
97 test->text_chan = tp_channel_new (test->connection, chan_path, NULL,
98 TP_HANDLE_TYPE_CONTACT, handle, &test->error);
99 g_assert_no_error (test->error);
100
101 tp_handle_unref (contact_repo, handle);
102
103 g_free (chan_path);
104 }
105
106 static void
teardown_channel_invalidated_cb(TpChannel * self,guint domain,gint code,gchar * message,Test * test)107 teardown_channel_invalidated_cb (TpChannel *self,
108 guint domain,
109 gint code,
110 gchar *message,
111 Test *test)
112 {
113 g_main_loop_quit (test->mainloop);
114 }
115
116 static void
teardown_run_close_channel(Test * test,TpChannel * channel)117 teardown_run_close_channel (Test *test, TpChannel *channel)
118 {
119 if (channel != NULL && tp_proxy_get_invalidated (channel) == NULL)
120 {
121 g_signal_connect (channel, "invalidated",
122 G_CALLBACK (teardown_channel_invalidated_cb), test);
123 tp_cli_channel_call_close (channel, -1, NULL, NULL, NULL, NULL);
124 g_main_loop_run (test->mainloop);
125 }
126 }
127
128 static void
teardown(Test * test,gconstpointer data)129 teardown (Test *test,
130 gconstpointer data)
131 {
132 teardown_run_close_channel (test, test->text_chan);
133
134 g_clear_error (&test->error);
135
136 g_object_unref (test->simple_handler);
137 g_object_unref (test->client);
138
139 tp_dbus_daemon_unregister_object (test->dbus, test->account_service);
140 g_object_unref (test->account_service);
141
142 tp_dbus_daemon_release_name (test->dbus, TP_ACCOUNT_MANAGER_BUS_NAME,
143 &test->error);
144 g_assert_no_error (test->error);
145
146 g_object_unref (test->dbus);
147 test->dbus = NULL;
148 g_main_loop_unref (test->mainloop);
149 test->mainloop = NULL;
150
151 g_object_unref (test->account);
152
153 g_object_unref (test->text_chan_service);
154 g_object_unref (test->text_chan);
155
156 tp_tests_connection_assert_disconnect_succeeds (test->connection);
157 g_object_unref (test->connection);
158 g_object_unref (test->base_connection);
159 }
160
161 static void
create_simple_handler(Test * test,gboolean bypass_approval,gboolean requests,TpSimpleHandlerHandleChannelsImpl impl)162 create_simple_handler (Test *test,
163 gboolean bypass_approval,
164 gboolean requests,
165 TpSimpleHandlerHandleChannelsImpl impl)
166 {
167 /* Create service-side Client object */
168 test->simple_handler = tp_tests_object_new_static_class (
169 TP_TYPE_SIMPLE_HANDLER,
170 "dbus-daemon", test->dbus,
171 "bypass-approval", bypass_approval,
172 "requests", requests,
173 "name", "MySimpleHandler",
174 "uniquify-name", FALSE,
175 "callback", impl,
176 "user-data", test,
177 "destroy", NULL,
178 NULL);
179 g_assert (test->simple_handler != NULL);
180
181 /* Create client-side Client object */
182 test->client = tp_tests_object_new_static_class (TP_TYPE_CLIENT,
183 "dbus-daemon", test->dbus,
184 "bus-name", tp_base_client_get_bus_name (test->simple_handler),
185 "object-path", tp_base_client_get_object_path (test->simple_handler),
186 NULL);
187
188 g_assert (test->client != NULL);
189 }
190
191 static void
get_client_prop_cb(TpProxy * proxy,GHashTable * properties,const GError * error,gpointer user_data,GObject * weak_object)192 get_client_prop_cb (TpProxy *proxy,
193 GHashTable *properties,
194 const GError *error,
195 gpointer user_data,
196 GObject *weak_object)
197 {
198 Test *test = user_data;
199 const gchar * const *interfaces;
200
201 if (error != NULL)
202 {
203 test->error = g_error_copy (error);
204 goto out;
205 }
206
207 g_assert_cmpint (g_hash_table_size (properties), == , 1);
208
209 interfaces = tp_asv_get_strv (properties, "Interfaces");
210 g_assert_cmpint (g_strv_length ((GStrv) interfaces), ==, 2);
211 g_assert (tp_strv_contains (interfaces, TP_IFACE_CLIENT_HANDLER));
212 g_assert (tp_strv_contains (interfaces, TP_IFACE_CLIENT_INTERFACE_REQUESTS));
213
214 out:
215 g_main_loop_quit (test->mainloop);
216 }
217
218 static void
check_filters(GPtrArray * filters)219 check_filters (GPtrArray *filters)
220 {
221 GHashTable *filter;
222
223 g_assert (filters != NULL);
224 g_assert_cmpuint (filters->len, ==, 2);
225
226 filter = g_ptr_array_index (filters, 0);
227 g_assert_cmpuint (g_hash_table_size (filter), ==, 1);
228 g_assert_cmpstr (tp_asv_get_string (filter, TP_PROP_CHANNEL_CHANNEL_TYPE), ==,
229 TP_IFACE_CHANNEL_TYPE_TEXT);
230
231 filter = g_ptr_array_index (filters, 1);
232 g_assert_cmpuint (g_hash_table_size (filter), ==, 2);
233 g_assert_cmpstr (tp_asv_get_string (filter, TP_PROP_CHANNEL_CHANNEL_TYPE), ==,
234 TP_IFACE_CHANNEL_TYPE_STREAM_TUBE);
235 g_assert_cmpuint (tp_asv_get_uint32 (filter,
236 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL), ==, TP_HANDLE_TYPE_CONTACT);
237 }
238
239 static void
get_handler_prop_cb(TpProxy * proxy,GHashTable * properties,const GError * error,gpointer user_data,GObject * weak_object)240 get_handler_prop_cb (TpProxy *proxy,
241 GHashTable *properties,
242 const GError *error,
243 gpointer user_data,
244 GObject *weak_object)
245 {
246 Test *test = user_data;
247 GPtrArray *filters;
248 gboolean bypass;
249 gboolean valid;
250 const gchar * const * capabilities;
251 GPtrArray *handled;
252
253 if (error != NULL)
254 {
255 test->error = g_error_copy (error);
256 goto out;
257 }
258
259 g_assert_cmpint (g_hash_table_size (properties), == , 4);
260
261 filters = tp_asv_get_boxed (properties, "HandlerChannelFilter",
262 TP_ARRAY_TYPE_CHANNEL_CLASS_LIST);
263 check_filters (filters);
264
265 bypass = tp_asv_get_boolean (properties, "BypassApproval", &valid);
266 g_assert (valid);
267 g_assert (!bypass);
268
269 capabilities = tp_asv_get_strv (properties, "Capabilities");
270 g_assert_cmpint (g_strv_length ((GStrv) capabilities), ==, 0);
271
272 handled = tp_asv_get_boxed (properties, "HandledChannels",
273 TP_ARRAY_TYPE_OBJECT_PATH_LIST);
274 g_assert (handled != NULL);
275 g_assert_cmpint (handled->len, ==, 0);
276
277 out:
278 g_main_loop_quit (test->mainloop);
279 }
280
281 static void
handle_channels_success(TpSimpleHandler * handler,TpAccount * account,TpConnection * connection,GList * channels,GList * requests_satisified,gint64 user_action_time,TpHandleChannelsContext * context,gpointer user_data)282 handle_channels_success (
283 TpSimpleHandler *handler,
284 TpAccount *account,
285 TpConnection *connection,
286 GList *channels,
287 GList *requests_satisified,
288 gint64 user_action_time,
289 TpHandleChannelsContext *context,
290 gpointer user_data)
291 {
292 tp_handle_channels_context_accept (context);
293 }
294
295 static void
test_properties(Test * test,gconstpointer data G_GNUC_UNUSED)296 test_properties (Test *test,
297 gconstpointer data G_GNUC_UNUSED)
298 {
299 create_simple_handler (test, FALSE, TRUE, handle_channels_success);
300
301 tp_base_client_add_handler_filter_vardict (test->simple_handler,
302 g_variant_new_parsed ("{ %s: <%s> }",
303 TP_PROP_CHANNEL_CHANNEL_TYPE, TP_IFACE_CHANNEL_TYPE_TEXT));
304
305 tp_base_client_add_handler_filter_vardict (test->simple_handler,
306 g_variant_new_parsed ("{ %s: <%s>, %s: <%u> }",
307 TP_PROP_CHANNEL_CHANNEL_TYPE, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE,
308 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, (guint32) TP_HANDLE_TYPE_CONTACT));
309
310 tp_base_client_register (test->simple_handler, &test->error);
311 g_assert_no_error (test->error);
312
313 /* Check Client properties */
314 tp_cli_dbus_properties_call_get_all (test->client, -1,
315 TP_IFACE_CLIENT, get_client_prop_cb, test, NULL, NULL);
316
317 g_main_loop_run (test->mainloop);
318 g_assert_no_error (test->error);
319
320 /* Check Handler properties */
321 tp_cli_dbus_properties_call_get_all (test->client, -1,
322 TP_IFACE_CLIENT_HANDLER, get_handler_prop_cb, test, NULL, NULL);
323
324 g_main_loop_run (test->mainloop);
325 g_assert_no_error (test->error);
326 }
327
328 static void
no_return_cb(TpClient * proxy,const GError * error,gpointer user_data,GObject * weak_object)329 no_return_cb (TpClient *proxy,
330 const GError *error,
331 gpointer user_data,
332 GObject *weak_object)
333 {
334 Test *test = user_data;
335
336 g_clear_error (&test->error);
337
338 if (error != NULL)
339 {
340 test->error = g_error_copy (error);
341 goto out;
342 }
343
344 out:
345 g_main_loop_quit (test->mainloop);
346 }
347
348 static void
add_channel_to_ptr_array(GPtrArray * arr,TpChannel * channel)349 add_channel_to_ptr_array (GPtrArray *arr,
350 TpChannel *channel)
351 {
352 GValueArray *tmp;
353
354 g_assert (arr != NULL);
355 g_assert (channel != NULL);
356
357 tmp = tp_value_array_build (2,
358 DBUS_TYPE_G_OBJECT_PATH, tp_proxy_get_object_path (channel),
359 TP_HASH_TYPE_STRING_VARIANT_MAP, tp_channel_borrow_immutable_properties (
360 channel),
361 G_TYPE_INVALID);
362
363 g_ptr_array_add (arr, tmp);
364 }
365
366 static void
free_channel_details(gpointer data,gpointer user_data)367 free_channel_details (gpointer data,
368 gpointer user_data)
369 {
370 g_boxed_free (TP_STRUCT_TYPE_CHANNEL_DETAILS, data);
371 }
372
373 static void
call_handle_channels(Test * test)374 call_handle_channels (Test *test)
375 {
376 GPtrArray *channels, *requests_satisified;
377 GHashTable *info;
378 int i;
379
380 channels = g_ptr_array_sized_new (1);
381 add_channel_to_ptr_array (channels, test->text_chan);
382
383 requests_satisified = g_ptr_array_sized_new (0);
384 info = g_hash_table_new (NULL, NULL);
385
386 tp_proxy_add_interface_by_id (TP_PROXY (test->client),
387 TP_IFACE_QUARK_CLIENT_HANDLER);
388
389 for (i = 0 ; i < 10 ; i ++)
390 {
391 tp_cli_client_handler_call_handle_channels (test->client, -1,
392 tp_proxy_get_object_path (test->account),
393 tp_proxy_get_object_path (test->connection),
394 channels, requests_satisified, 0, info,
395 no_return_cb, test, NULL, NULL);
396
397 g_main_loop_run (test->mainloop);
398 }
399
400 g_ptr_array_foreach (channels, free_channel_details, NULL);
401 g_ptr_array_unref (channels);
402 g_ptr_array_unref (requests_satisified);
403 g_hash_table_unref (info);
404 }
405
406 /* HandleChannels returns immediately */
407 static void
test_success(Test * test,gconstpointer data G_GNUC_UNUSED)408 test_success (Test *test,
409 gconstpointer data G_GNUC_UNUSED)
410 {
411 create_simple_handler (test, FALSE, FALSE, handle_channels_success);
412
413 tp_base_client_add_handler_filter_vardict (test->simple_handler,
414 g_variant_new_parsed ("@a{sv} {}"));
415
416 tp_base_client_register (test->simple_handler, &test->error);
417 g_assert_no_error (test->error);
418
419 call_handle_channels (test);
420 g_assert_no_error (test->error);
421 }
422
423 /* HandleChannels returns in an async way */
424 static gboolean
accept_idle_cb(gpointer data)425 accept_idle_cb (gpointer data)
426 {
427 TpHandleChannelsContext *context = data;
428
429 tp_handle_channels_context_accept (context);
430 g_object_unref (context);
431 return FALSE;
432 }
433
434 static void
handle_channels_async(TpSimpleHandler * handler,TpAccount * account,TpConnection * connection,GList * channels,GList * requests_satisified,gint64 user_action_time,TpHandleChannelsContext * context,gpointer user_data)435 handle_channels_async (
436 TpSimpleHandler *handler,
437 TpAccount *account,
438 TpConnection *connection,
439 GList *channels,
440 GList *requests_satisified,
441 gint64 user_action_time,
442 TpHandleChannelsContext *context,
443 gpointer user_data)
444 {
445 g_idle_add (accept_idle_cb, g_object_ref (context));
446
447 tp_handle_channels_context_delay (context);
448 }
449
450 static void
test_delayed(Test * test,gconstpointer data G_GNUC_UNUSED)451 test_delayed (Test *test,
452 gconstpointer data G_GNUC_UNUSED)
453 {
454 create_simple_handler (test, FALSE, FALSE, handle_channels_async);
455
456 tp_base_client_add_handler_filter_vardict (test->simple_handler,
457 g_variant_new_parsed ("@a{sv} {}"));
458
459 tp_base_client_register (test->simple_handler, &test->error);
460 g_assert_no_error (test->error);
461
462 call_handle_channels (test);
463 g_assert_no_error (test->error);
464 }
465
466 /* HandleChannels fails */
467 static void
handle_channels_fail(TpSimpleHandler * handler,TpAccount * account,TpConnection * connection,GList * channels,GList * requests_satisified,gint64 user_action_time,TpHandleChannelsContext * context,gpointer user_data)468 handle_channels_fail (
469 TpSimpleHandler *handler,
470 TpAccount *account,
471 TpConnection *connection,
472 GList *channels,
473 GList *requests_satisified,
474 gint64 user_action_time,
475 TpHandleChannelsContext *context,
476 gpointer user_data)
477 {
478 GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
479 "No HandleChannels for you!" };
480
481 tp_handle_channels_context_fail (context, &error);
482 }
483
484 static void
test_fail(Test * test,gconstpointer data G_GNUC_UNUSED)485 test_fail (Test *test,
486 gconstpointer data G_GNUC_UNUSED)
487 {
488 create_simple_handler (test, FALSE, FALSE, handle_channels_fail);
489
490 tp_base_client_add_handler_filter_vardict (test->simple_handler,
491 g_variant_new_parsed ("@a{sv} {}"));
492
493 tp_base_client_register (test->simple_handler, &test->error);
494 g_assert_no_error (test->error);
495
496 call_handle_channels (test);
497 g_assert_error (test->error, TP_ERROR, TP_ERROR_NOT_AVAILABLE);
498 }
499
500 int
main(int argc,char ** argv)501 main (int argc,
502 char **argv)
503 {
504 tp_tests_init (&argc, &argv);
505 g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
506
507 g_test_add ("/simple-handler/properties", Test, NULL, setup, test_properties,
508 teardown);
509 g_test_add ("/simple-handler/success", Test, NULL, setup, test_success,
510 teardown);
511 g_test_add ("/simple-handler/delayed", Test, NULL, setup, test_delayed,
512 teardown);
513 g_test_add ("/simple-handler/fail", Test, NULL, setup, test_fail,
514 teardown);
515
516 return tp_tests_run_with_bus ();
517 }
518