1 /* A very basic feature test for TpChannelRequest
2  *
3  * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
4  * Copyright (C) 2009 Nokia Corporation
5  *
6  * Copying and distribution of this file, with or without modification,
7  * are permitted in any medium without royalty provided the copyright
8  * notice and this notice are preserved.
9  */
10 
11 #include "config.h"
12 
13 #include <telepathy-glib/channel-request.h>
14 #include <telepathy-glib/defs.h>
15 #include <telepathy-glib/debug.h>
16 #include <telepathy-glib/svc-channel-request.h>
17 
18 #include <dbus/dbus.h>
19 #include <dbus/dbus-glib.h>
20 #include <dbus/dbus-glib-lowlevel.h>
21 
22 #include "tests/lib/simple-conn.h"
23 #include "tests/lib/util.h"
24 
25 /* This object implements no methods and no properties - TpChannelRequest
26  * doesn't actually use them yet */
27 
28 static GType test_simple_cr_get_type (void);
29 
30 typedef struct {
31     GObject parent;
32 } TestSimpleCR;
33 
34 typedef struct {
35     GObjectClass parent;
36 } TestSimpleCRClass;
37 
38 G_DEFINE_TYPE_WITH_CODE (TestSimpleCR, test_simple_cr, G_TYPE_OBJECT,
39     G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_REQUEST, NULL));
40 
41 static void
test_simple_cr_init(TestSimpleCR * self)42 test_simple_cr_init (TestSimpleCR *self)
43 {
44 }
45 
46 static void
test_simple_cr_class_init(TestSimpleCRClass * klass)47 test_simple_cr_class_init (TestSimpleCRClass *klass)
48 {
49 }
50 
51 typedef struct {
52     GMainLoop *mainloop;
53     TpDBusDaemon *dbus;
54 
55     DBusGConnection *private_conn;
56     TpDBusDaemon *private_dbus;
57     GObject *cr_service;
58 
59     /* Service side objects */
60     TpBaseConnection *base_connection;
61 
62     /* Client side objects */
63     TpConnection *connection;
64     TpChannel *channel;
65     TpChannelRequest *cr;
66 
67     GError *error /* initialized where needed */;
68 
69     guint succeeded;
70 } Test;
71 
72 static void
setup(Test * test,gconstpointer data)73 setup (Test *test,
74        gconstpointer data)
75 {
76   DBusConnection *libdbus;
77 
78   tp_debug_set_flags ("all");
79 
80   test->mainloop = g_main_loop_new (NULL, FALSE);
81   test->dbus = tp_tests_dbus_daemon_dup_or_die ();
82   g_assert (test->dbus != NULL);
83 
84   libdbus = dbus_bus_get_private (DBUS_BUS_STARTER, NULL);
85   g_assert (libdbus != NULL);
86   dbus_connection_setup_with_g_main (libdbus, NULL);
87   dbus_connection_set_exit_on_disconnect (libdbus, FALSE);
88   test->private_conn = dbus_connection_get_g_connection (libdbus);
89   /* transfer ref */
90   dbus_g_connection_ref (test->private_conn);
91   dbus_connection_unref (libdbus);
92   g_assert (test->private_conn != NULL);
93   test->private_dbus = tp_dbus_daemon_new (test->private_conn);
94   g_assert (test->private_dbus != NULL);
95 
96   /* Create (service and client sides) connection objects */
97   tp_tests_create_and_connect_conn (TP_TESTS_TYPE_SIMPLE_CONNECTION,
98       "me@test.com", &test->base_connection, &test->connection);
99   test->cr = NULL;
100 
101   test->cr_service = tp_tests_object_new_static_class (test_simple_cr_get_type (),
102       NULL);
103   tp_dbus_daemon_register_object (test->private_dbus, "/whatever",
104       test->cr_service);
105 }
106 
107 static void
teardown(Test * test,gconstpointer data)108 teardown (Test *test,
109           gconstpointer data)
110 {
111   tp_tests_connection_assert_disconnect_succeeds (test->connection);
112   g_object_unref (test->connection);
113   g_object_unref (test->base_connection);
114 
115   if (test->cr != NULL)
116     {
117       g_object_unref (test->cr);
118       test->cr = NULL;
119     }
120 
121   if (test->private_dbus != NULL)
122     {
123       tp_dbus_daemon_release_name (test->private_dbus,
124           TP_CHANNEL_DISPATCHER_BUS_NAME, NULL);
125 
126       g_object_unref (test->private_dbus);
127       test->private_dbus = NULL;
128     }
129 
130   g_object_unref (test->cr_service);
131   test->cr_service = NULL;
132 
133   if (test->private_conn != NULL)
134     {
135       dbus_connection_close (dbus_g_connection_get_connection (
136             test->private_conn));
137 
138       dbus_g_connection_unref (test->private_conn);
139       test->private_conn = NULL;
140     }
141 
142   /* make sure any pending things have happened */
143   tp_tests_proxy_run_until_dbus_queue_processed (test->dbus);
144 
145   g_object_unref (test->dbus);
146   test->dbus = NULL;
147 
148   g_main_loop_unref (test->mainloop);
149   test->mainloop = NULL;
150 }
151 
152 static void
test_new(Test * test,gconstpointer data G_GNUC_UNUSED)153 test_new (Test *test,
154           gconstpointer data G_GNUC_UNUSED)
155 {
156   gboolean ok;
157 
158   /* CD not running */
159   test->cr = tp_channel_request_new (test->dbus,
160       "/whatever", NULL, NULL);
161   g_assert (test->cr == NULL);
162 
163   ok = tp_dbus_daemon_request_name (test->private_dbus,
164       TP_CHANNEL_DISPATCHER_BUS_NAME, FALSE, NULL);
165   g_assert (ok);
166 
167   test->cr = tp_channel_request_new (test->dbus,
168       "not even syntactically valid", NULL, NULL);
169   g_assert (test->cr == NULL);
170 
171   test->cr = tp_channel_request_new (test->dbus, "/whatever", NULL, NULL);
172   g_assert (test->cr != NULL);
173 }
174 
175 static void
test_crash(Test * test,gconstpointer data G_GNUC_UNUSED)176 test_crash (Test *test,
177     gconstpointer data G_GNUC_UNUSED)
178 {
179   gboolean ok;
180 
181   ok = tp_dbus_daemon_request_name (test->private_dbus,
182       TP_CHANNEL_DISPATCHER_BUS_NAME, FALSE, NULL);
183   g_assert (ok);
184 
185   test->cr = tp_channel_request_new (test->dbus, "/whatever", NULL, NULL);
186   g_assert (test->cr != NULL);
187   g_assert (tp_proxy_get_invalidated (test->cr) == NULL);
188 
189   tp_dbus_daemon_release_name (test->private_dbus,
190       TP_CHANNEL_DISPATCHER_BUS_NAME, NULL);
191 
192   tp_tests_proxy_run_until_dbus_queue_processed (test->cr);
193 
194   g_assert (tp_proxy_get_invalidated (test->cr) == NULL);
195 
196   dbus_connection_close (dbus_g_connection_get_connection (
197         test->private_conn));
198   dbus_g_connection_unref (test->private_conn);
199   test->private_conn = NULL;
200 
201   while (tp_proxy_get_invalidated (test->cr) == NULL)
202     g_main_context_iteration (NULL, TRUE);
203 
204   g_assert (tp_proxy_get_invalidated (test->cr)->domain == TP_DBUS_ERRORS);
205   g_assert (tp_proxy_get_invalidated (test->cr)->code ==
206       TP_DBUS_ERROR_NAME_OWNER_LOST);
207 }
208 
209 static void
succeeded_cb(Test * test)210 succeeded_cb (Test *test)
211 {
212   test->succeeded++;
213 }
214 
215 static void
succeeded_with_channel_cb(TpChannelRequest * request,TpConnection * connection,TpChannel * channel,Test * test)216 succeeded_with_channel_cb (TpChannelRequest *request,
217     TpConnection *connection,
218     TpChannel *channel,
219     Test *test)
220 {
221   g_assert (TP_IS_CONNECTION (connection));
222   g_assert (TP_IS_CHANNEL (channel));
223 
224   g_assert_cmpstr (tp_proxy_get_object_path (connection), ==,
225       tp_base_connection_get_object_path (test->base_connection));
226   g_assert_cmpstr (tp_proxy_get_object_path (channel), ==,
227       "/Channel");
228 
229   test->succeeded++;
230 }
231 
232 static void
test_succeeded(Test * test,gconstpointer data G_GNUC_UNUSED)233 test_succeeded (Test *test,
234     gconstpointer data G_GNUC_UNUSED)
235 {
236   gboolean ok;
237   GHashTable *props;
238 
239   ok = tp_dbus_daemon_request_name (test->private_dbus,
240       TP_CHANNEL_DISPATCHER_BUS_NAME, FALSE, NULL);
241   g_assert (ok);
242 
243   test->cr = tp_channel_request_new (test->dbus, "/whatever", NULL, NULL);
244   g_assert (test->cr != NULL);
245   g_assert (tp_proxy_get_invalidated (test->cr) == NULL);
246 
247   g_signal_connect_swapped (test->cr, "succeeded", G_CALLBACK (succeeded_cb),
248       test);
249   g_signal_connect (test->cr, "succeeded-with-channel",
250       G_CALLBACK (succeeded_with_channel_cb), test);
251 
252   /* sync up both sockets to ensure that the match rules are in place */
253   tp_tests_proxy_run_until_dbus_queue_processed (test->cr);
254 
255   props = g_hash_table_new (NULL, NULL);
256 
257   tp_svc_channel_request_emit_succeeded_with_channel (test->cr_service,
258       tp_base_connection_get_object_path (test->base_connection),
259       props, "/Channel", props);
260 
261   g_hash_table_unref (props);
262 
263   tp_svc_channel_request_emit_succeeded (test->cr_service);
264 
265   tp_tests_proxy_run_until_dbus_queue_processed (test->cr);
266 
267   g_assert (tp_proxy_get_invalidated (test->cr) != NULL);
268   g_assert (tp_proxy_get_invalidated (test->cr)->domain == TP_DBUS_ERRORS);
269   g_assert (tp_proxy_get_invalidated (test->cr)->code ==
270       TP_DBUS_ERROR_OBJECT_REMOVED);
271   g_assert_cmpuint (test->succeeded, ==, 2);
272 
273   g_signal_handlers_disconnect_by_func (test->cr, G_CALLBACK (succeeded_cb),
274       test);
275 }
276 
277 static void
test_failed(Test * test,gconstpointer data G_GNUC_UNUSED)278 test_failed (Test *test,
279     gconstpointer data G_GNUC_UNUSED)
280 {
281   gboolean ok;
282 
283   ok = tp_dbus_daemon_request_name (test->private_dbus,
284       TP_CHANNEL_DISPATCHER_BUS_NAME, FALSE, NULL);
285   g_assert (ok);
286 
287   test->cr = tp_channel_request_new (test->dbus, "/whatever", NULL, NULL);
288   g_assert (test->cr != NULL);
289   g_assert (tp_proxy_get_invalidated (test->cr) == NULL);
290 
291   g_signal_connect_swapped (test->cr, "succeeded", G_CALLBACK (succeeded_cb),
292       test);
293 
294   /* sync up both sockets to ensure that the match rules are in place */
295   tp_tests_proxy_run_until_dbus_queue_processed (test->cr);
296 
297   tp_svc_channel_request_emit_failed (test->cr_service,
298       TP_ERROR_STR_NOT_YOURS, "lalala");
299 
300   tp_tests_proxy_run_until_dbus_queue_processed (test->cr);
301 
302   g_assert (tp_proxy_get_invalidated (test->cr) != NULL);
303   g_assert (tp_proxy_get_invalidated (test->cr)->domain == TP_ERROR);
304   g_assert (tp_proxy_get_invalidated (test->cr)->code == TP_ERROR_NOT_YOURS);
305   g_assert_cmpstr (tp_proxy_get_invalidated (test->cr)->message, ==,
306       "lalala");
307   g_assert_cmpuint (test->succeeded, ==, 0);
308 
309   g_signal_handlers_disconnect_by_func (test->cr, G_CALLBACK (succeeded_cb),
310       test);
311 }
312 
313 static void
test_immutable_properties(Test * test,gconstpointer data G_GNUC_UNUSED)314 test_immutable_properties (Test *test,
315     gconstpointer data G_GNUC_UNUSED)
316 {
317   gboolean ok;
318   GHashTable *props;
319   GVariant *vardict;
320 
321   props = tp_asv_new ("badger", G_TYPE_UINT, 42,
322       NULL);
323 
324   ok = tp_dbus_daemon_request_name (test->private_dbus,
325       TP_CHANNEL_DISPATCHER_BUS_NAME, FALSE, NULL);
326   g_assert (ok);
327 
328   test->cr = tp_channel_request_new (test->dbus, "/whatever", props, NULL);
329   g_assert (test->cr != NULL);
330 
331   g_hash_table_unref (props);
332 
333   props = (GHashTable *) tp_channel_request_get_immutable_properties (test->cr);
334   g_assert_cmpuint (tp_asv_get_uint32 (props, "badger", NULL), ==, 42);
335 
336   g_object_get (test->cr, "immutable-properties", &props, NULL);
337   g_assert_cmpuint (tp_asv_get_uint32 (props, "badger", NULL), ==, 42);
338 
339   g_hash_table_unref (props);
340 
341   vardict = tp_channel_request_dup_immutable_properties (test->cr);
342   g_assert_cmpuint (tp_vardict_get_uint32 (vardict, "badger", NULL), ==, 42);
343   g_variant_unref (vardict);
344 
345   g_object_get (test->cr,
346       "immutable-properties-vardict", &vardict, NULL);
347   g_assert_cmpuint (tp_vardict_get_uint32 (vardict, "badger", NULL), ==, 42);
348   g_variant_unref (vardict);
349 }
350 
351 #define ACCOUNT_PATH TP_ACCOUNT_OBJECT_PATH_BASE "a/b/c"
352 
353 static void
test_properties(Test * test,gconstpointer data G_GNUC_UNUSED)354 test_properties (Test *test,
355     gconstpointer data G_GNUC_UNUSED)
356 {
357   gboolean ok;
358   GHashTable *props, *hints;
359   TpAccount *account;
360   gint64 user_action_time;
361   const gchar *handler;
362   GVariant *vardict;
363 
364   hints = tp_asv_new ("test", G_TYPE_STRING, "hi", NULL);
365 
366   props = tp_asv_new (
367       TP_PROP_CHANNEL_REQUEST_ACCOUNT, DBUS_TYPE_G_OBJECT_PATH, ACCOUNT_PATH,
368       TP_PROP_CHANNEL_REQUEST_USER_ACTION_TIME, G_TYPE_INT64, (gint64) 12345,
369       TP_PROP_CHANNEL_REQUEST_PREFERRED_HANDLER, G_TYPE_STRING, "Badger",
370       TP_PROP_CHANNEL_REQUEST_HINTS, TP_HASH_TYPE_STRING_VARIANT_MAP, hints,
371       NULL);
372 
373   ok = tp_dbus_daemon_request_name (test->private_dbus,
374       TP_CHANNEL_DISPATCHER_BUS_NAME, FALSE, NULL);
375   g_assert (ok);
376 
377   test->cr = tp_channel_request_new (test->dbus, "/whatever", props, NULL);
378   g_assert (test->cr != NULL);
379 
380   g_hash_table_unref (props);
381   g_hash_table_unref (hints);
382 
383   /* Account */
384   account = tp_channel_request_get_account (test->cr);
385   g_assert (TP_IS_ACCOUNT (account));
386   g_assert_cmpstr (tp_proxy_get_object_path (account), ==, ACCOUNT_PATH);
387 
388   g_object_get (test->cr, "account", &account, NULL);
389   g_assert (TP_IS_ACCOUNT (account));
390   g_assert_cmpstr (tp_proxy_get_object_path (account), ==, ACCOUNT_PATH);
391   g_object_unref (account);
392 
393   /* UserActionTime */
394   user_action_time = tp_channel_request_get_user_action_time (test->cr);
395   g_assert_cmpint (user_action_time, ==, 12345);
396 
397   g_object_get (test->cr, "user-action-time", &user_action_time, NULL);
398   g_assert_cmpint (user_action_time, ==, 12345);
399 
400   /* PreferredHandler */
401   handler = tp_channel_request_get_preferred_handler (test->cr);
402   g_assert_cmpstr (handler, ==, "Badger");
403 
404   g_object_get (test->cr, "preferred-handler", &handler, NULL);
405   g_assert_cmpstr (handler, ==, "Badger");
406 
407   /* Hints */
408   hints = (GHashTable *) tp_channel_request_get_hints (test->cr);
409   g_assert_cmpstr (tp_asv_get_string (hints, "test"), ==, "hi");
410 
411   g_object_get (test->cr, "hints", &hints, NULL);
412   g_assert_cmpstr (tp_asv_get_string (hints, "test"), ==, "hi");
413 
414   g_hash_table_unref (hints);
415 
416   vardict = tp_channel_request_dup_hints (test->cr);
417   g_assert_cmpstr (tp_vardict_get_string (vardict, "test"), ==, "hi");
418   g_variant_unref (vardict);
419 
420   g_object_get (test->cr,
421       "hints-vardict", &vardict,
422       NULL);
423   g_assert_cmpstr (tp_vardict_get_string (vardict, "test"), ==, "hi");
424   g_variant_unref (vardict);
425 }
426 
427 int
main(int argc,char ** argv)428 main (int argc,
429       char **argv)
430 {
431   tp_tests_init (&argc, &argv);
432   g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
433 
434   g_test_add ("/cr/new", Test, NULL, setup, test_new, teardown);
435   g_test_add ("/cr/crash", Test, NULL, setup, test_crash, teardown);
436   g_test_add ("/cr/succeeded", Test, NULL, setup, test_succeeded, teardown);
437   g_test_add ("/cr/failed", Test, NULL, setup, test_failed, teardown);
438   g_test_add ("/cr/immutable-properties", Test, NULL, setup,
439       test_immutable_properties, teardown);
440   g_test_add ("/cr/properties", Test, NULL, setup, test_properties, teardown);
441 
442   return tp_tests_run_with_bus ();
443 }
444