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