1 /* Tests of TpBaseClient
2  *
3  * Copyright © 2010-2011 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/telepathy-glib.h>
13 
14 #include "tests/lib/util.h"
15 #include "tests/lib/simple-account.h"
16 #include "tests/lib/simple-conn.h"
17 #include "tests/lib/my-conn-proxy.h"
18 
19 typedef struct {
20     GMainLoop *mainloop;
21     TpDBusDaemon *dbus;
22 
23     /* Service side objects */
24     TpBaseConnection *base_connection;
25 
26     /* Client side objects */
27     TpConnection *connection;
28     TpTestsMyConnProxy *my_conn;
29 
30     GError *error /* initialized where needed */;
31     gint wait;
32 } Test;
33 
34 static void
setup(Test * test,gconstpointer data)35 setup (Test *test,
36        gconstpointer data)
37 {
38   test->mainloop = g_main_loop_new (NULL, FALSE);
39   test->dbus = tp_tests_dbus_daemon_dup_or_die ();
40 
41   test->error = NULL;
42 
43   /* Create (service and client sides) connection objects */
44   tp_tests_create_and_connect_conn (TP_TESTS_TYPE_SIMPLE_CONNECTION,
45       "me@test.com", &test->base_connection, &test->connection);
46 
47   test->my_conn = g_object_new (TP_TESTS_TYPE_MY_CONN_PROXY,
48       "dbus-daemon", test->dbus,
49       "bus-name", tp_proxy_get_bus_name (test->connection),
50       "object-path", tp_proxy_get_object_path (test->connection),
51       NULL);
52 }
53 
54 static void
disconnect_and_destroy_conn(Test * test)55 disconnect_and_destroy_conn (Test *test)
56 {
57   tp_tests_connection_assert_disconnect_succeeds (
58       TP_CONNECTION (test->my_conn));
59 
60   tp_clear_object (&test->connection);
61   tp_clear_object (&test->base_connection);
62   tp_clear_object (&test->my_conn);
63 
64 }
65 
66 static void
teardown(Test * test,gconstpointer data)67 teardown (Test *test,
68           gconstpointer data)
69 {
70   g_clear_error (&test->error);
71 
72   tp_clear_object (&test->dbus);
73   g_main_loop_unref (test->mainloop);
74   test->mainloop = NULL;
75 
76   disconnect_and_destroy_conn (test);
77 }
78 
79 static void
prepare_cb(GObject * source,GAsyncResult * result,gpointer user_data)80 prepare_cb (GObject *source,
81     GAsyncResult *result,
82     gpointer user_data)
83 {
84   Test *test = user_data;
85 
86   tp_proxy_prepare_finish (TP_PROXY (source), result, &test->error);
87 
88   test->wait--;
89   if (test->wait <= 0)
90     g_main_loop_quit (test->mainloop);
91 }
92 
93 static void
test_prepare_capabilities(Test * test,gconstpointer data G_GNUC_UNUSED)94 test_prepare_capabilities (Test *test,
95     gconstpointer data G_GNUC_UNUSED)
96 {
97   /* Prepare capabilities on a new proxy. CORE should be automatically prepared
98    * *before* checking if Requests is implemented as
99    * tp_proxy_has_interface_by_id() can't work without CORE. */
100   GQuark features[] = { TP_CONNECTION_FEATURE_CAPABILITIES, 0 };
101 
102   tp_proxy_prepare_async (test->my_conn, features, prepare_cb, test);
103 
104   g_main_loop_run (test->mainloop);
105   g_assert_no_error (test->error);
106 
107   g_assert (tp_proxy_is_prepared (test->my_conn, TP_CONNECTION_FEATURE_CORE));
108   g_assert (tp_proxy_is_prepared (test->my_conn,
109         TP_CONNECTION_FEATURE_CAPABILITIES));
110 }
111 
112 static void
test_prepare_core(Test * test,gconstpointer data G_GNUC_UNUSED)113 test_prepare_core (Test *test,
114     gconstpointer data G_GNUC_UNUSED)
115 {
116   /* Test than preparing the 'top' core feature prepare the other core
117    * features as well */
118   GQuark features[] = { TP_TESTS_MY_CONN_PROXY_FEATURE_CORE, 0 };
119 
120   tp_proxy_prepare_async (test->my_conn, features, prepare_cb, test);
121 
122   g_main_loop_run (test->mainloop);
123   g_assert_no_error (test->error);
124 
125   g_assert (tp_proxy_is_prepared (test->my_conn,
126         TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
127   g_assert (tp_proxy_is_prepared (test->my_conn, TP_CONNECTION_FEATURE_CORE));
128 
129   g_assert (!tp_proxy_is_prepared (test->my_conn,
130         TP_CONNECTION_FEATURE_CAPABILITIES));
131 }
132 
133 static void
test_depends(Test * test,gconstpointer data G_GNUC_UNUSED)134 test_depends (Test *test,
135     gconstpointer data G_GNUC_UNUSED)
136 {
137   /* Test if A is automatically prepared when preparing B */
138   GQuark features[] = { TP_TESTS_MY_CONN_PROXY_FEATURE_B, 0 };
139 
140   tp_proxy_prepare_async (test->my_conn, features, prepare_cb, test);
141 
142   g_main_loop_run (test->mainloop);
143   g_assert_no_error (test->error);
144 
145   g_assert (tp_proxy_is_prepared (test->my_conn,
146         TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
147   g_assert (tp_proxy_is_prepared (test->my_conn,
148         TP_TESTS_MY_CONN_PROXY_FEATURE_A));
149   g_assert (tp_proxy_is_prepared (test->my_conn,
150         TP_TESTS_MY_CONN_PROXY_FEATURE_B));
151 }
152 
153 static void
test_wrong_iface(Test * test,gconstpointer data G_GNUC_UNUSED)154 test_wrong_iface (Test *test,
155     gconstpointer data G_GNUC_UNUSED)
156 {
157   /* Feature can't be prepared because proxy doesn't support the right
158    * interface */
159   GQuark features[] = { TP_TESTS_MY_CONN_PROXY_FEATURE_WRONG_IFACE, 0 };
160 
161   tp_proxy_prepare_async (test->my_conn, features, prepare_cb, test);
162 
163   g_main_loop_run (test->mainloop);
164   g_assert_no_error (test->error);
165 
166   g_assert (tp_proxy_is_prepared (test->my_conn,
167         TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
168   g_assert (!tp_proxy_is_prepared (test->my_conn,
169         TP_TESTS_MY_CONN_PROXY_FEATURE_WRONG_IFACE));
170 }
171 
172 static void
test_bad_dep(Test * test,gconstpointer data G_GNUC_UNUSED)173 test_bad_dep (Test *test,
174     gconstpointer data G_GNUC_UNUSED)
175 {
176   /* Feature can't be prepared because it depends on an unpreparable
177    * feature */
178   GQuark features[] = { TP_TESTS_MY_CONN_PROXY_FEATURE_BAD_DEP, 0 };
179 
180   tp_proxy_prepare_async (test->my_conn, features, prepare_cb, test);
181 
182   g_main_loop_run (test->mainloop);
183   g_assert_no_error (test->error);
184 
185   g_assert (tp_proxy_is_prepared (test->my_conn,
186         TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
187   g_assert (!tp_proxy_is_prepared (test->my_conn,
188         TP_TESTS_MY_CONN_PROXY_FEATURE_WRONG_IFACE));
189   g_assert (!tp_proxy_is_prepared (test->my_conn,
190         TP_TESTS_MY_CONN_PROXY_FEATURE_BAD_DEP));
191 }
192 
193 static void
test_fail(Test * test,gconstpointer data G_GNUC_UNUSED)194 test_fail (Test *test,
195     gconstpointer data G_GNUC_UNUSED)
196 {
197   /* Feature preparation fails */
198   GQuark features[] = { TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL, 0 };
199 
200   tp_proxy_prepare_async (test->my_conn, features, prepare_cb, test);
201 
202   g_main_loop_run (test->mainloop);
203   g_assert_no_error (test->error);
204 
205   g_assert (tp_proxy_is_prepared (test->my_conn,
206         TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
207   g_assert (!tp_proxy_is_prepared (test->my_conn,
208         TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL));
209 }
210 
211 static void
test_fail_dep(Test * test,gconstpointer data G_GNUC_UNUSED)212 test_fail_dep (Test *test,
213     gconstpointer data G_GNUC_UNUSED)
214 {
215   /* Feature can't be prepared because its deps can't be prepared */
216   GQuark features[] = { TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL_DEP, 0 };
217 
218   tp_proxy_prepare_async (test->my_conn, features, prepare_cb, test);
219 
220   g_main_loop_run (test->mainloop);
221   g_assert_no_error (test->error);
222 
223   g_assert (tp_proxy_is_prepared (test->my_conn,
224         TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
225   g_assert (!tp_proxy_is_prepared (test->my_conn,
226         TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL));
227   g_assert (!tp_proxy_is_prepared (test->my_conn,
228         TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL_DEP));
229 }
230 
231 static void
test_retry(Test * test,gconstpointer data G_GNUC_UNUSED)232 test_retry (Test *test,
233     gconstpointer data G_GNUC_UNUSED)
234 {
235   /* We have the prepare the feature twice */
236   GQuark features[] = { TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY, 0 };
237 
238   tp_proxy_prepare_async (test->my_conn, features, prepare_cb, test);
239 
240   g_main_loop_run (test->mainloop);
241   g_assert_no_error (test->error);
242 
243   g_assert (tp_proxy_is_prepared (test->my_conn,
244         TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
245   g_assert (!tp_proxy_is_prepared (test->my_conn,
246         TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY));
247 
248   /* second attempt */
249   test->my_conn->retry_feature_success = TRUE;
250   tp_proxy_prepare_async (test->my_conn, features, prepare_cb, test);
251 
252   g_main_loop_run (test->mainloop);
253   g_assert_no_error (test->error);
254 
255   g_assert (tp_proxy_is_prepared (test->my_conn,
256         TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
257   g_assert (tp_proxy_is_prepared (test->my_conn,
258         TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY));
259 }
260 
261 static void
test_retry_dep(Test * test,gconstpointer data G_GNUC_UNUSED)262 test_retry_dep (Test *test,
263     gconstpointer data G_GNUC_UNUSED)
264 {
265   /* RETRY_DEP depends on a feature having can_retry and which failed, so
266    * preparing RETRY_DEP will re-prepare it successfully */
267   GQuark features_retry[] = { TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY, 0 };
268   GQuark features_retry_dep[] = { TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY_DEP, 0 };
269 
270   /* Try preparing TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY, will fail */
271   tp_proxy_prepare_async (test->my_conn, features_retry, prepare_cb, test);
272 
273   g_main_loop_run (test->mainloop);
274   g_assert_no_error (test->error);
275 
276   g_assert (tp_proxy_is_prepared (test->my_conn,
277         TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
278   g_assert (!tp_proxy_is_prepared (test->my_conn,
279         TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY));
280   g_assert (!tp_proxy_is_prepared (test->my_conn,
281         TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY_DEP));
282 
283   /* Try prepare TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY_DEP, will re-prepare
284    * TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY */
285   test->my_conn->retry_feature_success = TRUE;
286   tp_proxy_prepare_async (test->my_conn, features_retry_dep, prepare_cb, test);
287 
288   g_main_loop_run (test->mainloop);
289   g_assert_no_error (test->error);
290 
291   g_assert (tp_proxy_is_prepared (test->my_conn,
292         TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
293   g_assert (tp_proxy_is_prepared (test->my_conn,
294         TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY));
295   g_assert (tp_proxy_is_prepared (test->my_conn,
296         TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY_DEP));
297 }
298 
299 static void
recreate_connection(Test * test)300 recreate_connection (Test *test)
301 {
302   gchar *name;
303   gchar *conn_path;
304 
305   disconnect_and_destroy_conn (test);
306 
307   test->base_connection = tp_tests_object_new_static_class (
308       TP_TESTS_TYPE_SIMPLE_CONNECTION,
309       "account", "me@test.com",
310       "protocol", "simple",
311       NULL);
312   g_assert (test->base_connection != NULL);
313 
314   g_assert (tp_base_connection_register (test->base_connection, "simple",
315         &name, &conn_path, &test->error));
316   g_assert_no_error (test->error);
317 
318   test->connection = tp_connection_new (test->dbus, name, conn_path,
319       &test->error);
320   g_assert_no_error (test->error);
321 
322   test->my_conn = g_object_new (TP_TESTS_TYPE_MY_CONN_PROXY,
323       "dbus-daemon", test->dbus,
324       "bus-name", tp_proxy_get_bus_name (test->connection),
325       "object-path", tp_proxy_get_object_path (test->connection),
326       NULL);
327   g_assert (test->my_conn != NULL);
328 
329   g_free (name);
330   g_free (conn_path);
331 }
332 
333 static void
test_before_connected(Test * test,gconstpointer data G_GNUC_UNUSED)334 test_before_connected (Test *test,
335     gconstpointer data G_GNUC_UNUSED)
336 {
337   GQuark features[] = { TP_TESTS_MY_CONN_PROXY_FEATURE_BEFORE_CONNECTED, 0 };
338   GQuark connected[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 };
339 
340   /* We need a not yet connected connection */
341   recreate_connection (test);
342 
343   g_assert_cmpuint (test->my_conn->before_connected_state, ==,
344       BEFORE_CONNECTED_STATE_UNPREPARED);
345 
346   /* Connection is not yet connected, prepare the feature */
347   tp_proxy_prepare_async (test->my_conn, features, prepare_cb, test);
348 
349   g_main_loop_run (test->mainloop);
350   g_assert_no_error (test->error);
351 
352   g_assert (tp_proxy_is_prepared (test->my_conn,
353         TP_TESTS_MY_CONN_PROXY_FEATURE_BEFORE_CONNECTED));
354 
355   g_assert_cmpuint (test->my_conn->before_connected_state, ==,
356       BEFORE_CONNECTED_STATE_NOT_CONNECTED);
357 
358   tp_cli_connection_call_connect (test->connection, -1, NULL, NULL, NULL, NULL);
359 
360   /* Wait that CONNECTED is announced */
361   tp_proxy_prepare_async (test->my_conn, connected, prepare_cb, test);
362 
363   g_main_loop_run (test->mainloop);
364   g_assert_no_error (test->error);
365 
366   /* state has been updated */
367   g_assert_cmpuint (test->my_conn->before_connected_state, ==,
368       BEFORE_CONNECTED_STATE_CONNECTED);
369 }
370 
371 static void
test_interface_later(Test * test,gconstpointer data G_GNUC_UNUSED)372 test_interface_later (Test *test,
373     gconstpointer data G_GNUC_UNUSED)
374 {
375   GQuark features[] = { TP_TESTS_MY_CONN_PROXY_FEATURE_INTERFACE_LATER, 0 };
376   GQuark connected[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 };
377   const gchar *interfaces[] = { TP_TESTS_MY_CONN_PROXY_IFACE_LATER, NULL };
378 
379   /* We need a not yet connected connection */
380   recreate_connection (test);
381 
382   /* Try preparing before the connection is connected */
383   tp_proxy_prepare_async (test->my_conn, features, prepare_cb, test);
384 
385   g_main_loop_run (test->mainloop);
386   g_assert_no_error (test->error);
387 
388   /* Feature isn't prepared */
389   g_assert (!tp_proxy_is_prepared (test->my_conn,
390         TP_TESTS_MY_CONN_PROXY_FEATURE_INTERFACE_LATER));
391 
392   tp_cli_connection_call_connect (test->connection, -1, NULL, NULL, NULL, NULL);
393 
394   /* While connecting the interface is added */
395   tp_base_connection_add_interfaces (test->base_connection, interfaces);
396 
397   /* Wait that CONNECTED is announced */
398   tp_proxy_prepare_async (test->my_conn, connected, prepare_cb, test);
399 
400   g_main_loop_run (test->mainloop);
401   g_assert_no_error (test->error);
402 
403   /* The feature has been prepared now */
404   g_assert (tp_proxy_is_prepared (test->my_conn,
405         TP_TESTS_MY_CONN_PROXY_FEATURE_INTERFACE_LATER));
406 }
407 
408 int
main(int argc,char ** argv)409 main (int argc,
410       char **argv)
411 {
412   tp_tests_init (&argc, &argv);
413   g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
414 
415   g_test_add ("/proxy-preparation/prepare-capabilities", Test, NULL, setup,
416       test_prepare_capabilities, teardown);
417   g_test_add ("/proxy-preparation/prepare-core", Test, NULL, setup,
418       test_prepare_core, teardown);
419   g_test_add ("/proxy-preparation/depends", Test, NULL, setup,
420       test_depends, teardown);
421   g_test_add ("/proxy-preparation/wrong-iface", Test, NULL, setup,
422       test_wrong_iface, teardown);
423   g_test_add ("/proxy-preparation/bad-dep", Test, NULL, setup,
424       test_bad_dep, teardown);
425   g_test_add ("/proxy-preparation/fail", Test, NULL, setup,
426       test_fail, teardown);
427   g_test_add ("/proxy-preparation/fail-dep", Test, NULL, setup,
428       test_fail_dep, teardown);
429   g_test_add ("/proxy-preparation/retry", Test, NULL, setup,
430       test_retry, teardown);
431   g_test_add ("/proxy-preparation/retry-dep", Test, NULL, setup,
432       test_retry_dep, teardown);
433   g_test_add ("/proxy-preparation/before-connected", Test, NULL, setup,
434       test_before_connected, teardown);
435   g_test_add ("/proxy-preparation/interface-later", Test, NULL, setup,
436       test_interface_later, teardown);
437 
438   return tp_tests_run_with_bus ();
439 }
440