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