1 /* Feature test for https://bugs.freedesktop.org/show_bug.cgi?id=15300
2 *
3 * Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/>
4 * Copyright (C) 2007-2008 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/connection.h>
14 #include <telepathy-glib/dbus.h>
15 #include <telepathy-glib/debug.h>
16 #include <telepathy-glib/interfaces.h>
17 #include <telepathy-glib/proxy-subclass.h>
18
19 #include "tests/lib/myassert.h"
20 #include "tests/lib/simple-conn.h"
21 #include "tests/lib/util.h"
22
23 typedef struct {
24 TpDBusDaemon *dbus;
25 TpTestsSimpleConnection *service_conn;
26 TpBaseConnection *service_conn_as_base;
27 gchar *conn_name;
28 gchar *conn_path;
29 TpConnection *conn;
30
31 gboolean cwr_ready;
32 GError *cwr_error /* initialized in setup */;
33
34 GAsyncResult *prepare_result;
35 } Test;
36
37 static GError invalidated_for_test = { 0, TP_ERROR_PERMISSION_DENIED,
38 "No connection for you!" };
39
40 static void
connection_prepared_cb(GObject * object,GAsyncResult * res,gpointer user_data)41 connection_prepared_cb (GObject *object,
42 GAsyncResult *res,
43 gpointer user_data)
44 {
45 Test *test = user_data;
46
47 g_message ("%p prepared", object);
48 g_assert (test->prepare_result == NULL);
49 test->prepare_result = g_object_ref (res);
50 }
51
52 static void
setup(Test * test,gconstpointer data)53 setup (Test *test,
54 gconstpointer data)
55 {
56 GError *error = NULL;
57
58 invalidated_for_test.domain = TP_ERROR;
59
60 tp_debug_set_flags ("all");
61 test->dbus = tp_tests_dbus_daemon_dup_or_die ();
62
63 test->service_conn = TP_TESTS_SIMPLE_CONNECTION (
64 tp_tests_object_new_static_class (
65 TP_TESTS_TYPE_SIMPLE_CONNECTION,
66 "account", "me@example.com",
67 "protocol", "simple-protocol",
68 NULL));
69 test->service_conn_as_base = TP_BASE_CONNECTION (test->service_conn);
70 g_assert (test->service_conn != NULL);
71 g_assert (test->service_conn_as_base != NULL);
72
73 g_assert (tp_base_connection_register (test->service_conn_as_base, "simple",
74 &test->conn_name, &test->conn_path, &error));
75 g_assert_no_error (error);
76
77 test->cwr_ready = FALSE;
78 test->cwr_error = NULL;
79 }
80
81 static void
teardown(Test * test,gconstpointer data)82 teardown (Test *test,
83 gconstpointer data)
84 {
85 TpConnection *conn;
86 GError *error = NULL;
87
88 if (test->conn != NULL)
89 {
90 g_object_unref (test->conn);
91 test->conn = NULL;
92 }
93
94 /* disconnect the connection so we don't leak it */
95 conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path,
96 &error);
97 g_assert (conn != NULL);
98 g_assert_no_error (error);
99
100 tp_tests_connection_assert_disconnect_succeeds (conn);
101
102 g_assert (!tp_connection_run_until_ready (conn, FALSE, &error, NULL));
103 g_assert_error (error, TP_ERROR, TP_ERROR_CANCELLED);
104 g_clear_error (&error);
105
106 test->service_conn_as_base = NULL;
107 g_object_unref (test->service_conn);
108 g_free (test->conn_name);
109 g_free (test->conn_path);
110
111 g_object_unref (test->dbus);
112 test->dbus = NULL;
113 }
114
115 static void
test_run_until_invalid(Test * test,gconstpointer nil G_GNUC_UNUSED)116 test_run_until_invalid (Test *test,
117 gconstpointer nil G_GNUC_UNUSED)
118 {
119 GError *error = NULL;
120
121 test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path,
122 &error);
123 g_assert (test->conn != NULL);
124 g_assert_no_error (error);
125 tp_proxy_invalidate ((TpProxy *) test->conn, &invalidated_for_test);
126
127 MYASSERT (!tp_connection_run_until_ready (test->conn, TRUE, &error, NULL),
128 "");
129 g_assert (error != NULL);
130 g_assert_error (error, invalidated_for_test.domain,
131 invalidated_for_test.code);
132 g_assert_cmpstr (error->message, ==, invalidated_for_test.message);
133 g_error_free (error);
134 }
135
136 static void
test_run_until_ready(Test * test,gconstpointer nil G_GNUC_UNUSED)137 test_run_until_ready (Test *test,
138 gconstpointer nil G_GNUC_UNUSED)
139 {
140 GError *error = NULL;
141
142 test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path,
143 &error);
144 g_assert (test->conn != NULL);
145 g_assert_no_error (error);
146
147 MYASSERT (tp_connection_run_until_ready (test->conn, TRUE, &error, NULL),
148 "");
149 g_assert_no_error (error);
150 }
151
152 static void
conn_ready(TpConnection * connection,const GError * error,gpointer user_data)153 conn_ready (TpConnection *connection,
154 const GError *error,
155 gpointer user_data)
156 {
157 Test *test = user_data;
158
159 test->cwr_ready = TRUE;
160
161 if (error == NULL)
162 {
163 gboolean parsed;
164 gchar *proto = NULL;
165 gchar *cm_name = NULL;
166
167 g_message ("connection %p ready", connection);
168 parsed = tp_connection_parse_object_path (connection, &proto, &cm_name);
169 g_assert (parsed);
170 g_assert_cmpstr (proto, ==, "simple-protocol");
171 g_assert_cmpstr (cm_name, ==, "simple");
172 g_free (proto);
173 g_free (cm_name);
174 }
175 else
176 {
177 g_message ("connection %p invalidated: %s #%u \"%s\"", connection,
178 g_quark_to_string (error->domain), error->code, error->message);
179
180 test->cwr_error = g_error_copy (error);
181 }
182 }
183
184 static void
test_prepare(Test * test,gconstpointer nil G_GNUC_UNUSED)185 test_prepare (Test *test,
186 gconstpointer nil G_GNUC_UNUSED)
187 {
188 GError *error = NULL;
189 GQuark features[] = { TP_CONNECTION_FEATURE_CONNECTED,
190 TP_CONNECTION_FEATURE_CAPABILITIES, 0 };
191 TpConnectionStatusReason reason;
192 TpCapabilities *caps;
193 GPtrArray *classes;
194 gchar *cm_name, *protocol_name;
195
196 test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path,
197 &error);
198 g_assert (test->conn != NULL);
199 g_assert_no_error (error);
200
201 g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE));
202 g_assert (!tp_proxy_is_prepared (test->conn,
203 TP_CONNECTION_FEATURE_CONNECTED));
204
205 tp_proxy_prepare_async (test->conn, NULL, connection_prepared_cb, test);
206 /* this is not synchronous */
207 g_assert (test->prepare_result == NULL);
208 g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE));
209
210 while (test->prepare_result == NULL)
211 g_main_context_iteration (NULL, TRUE);
212
213 g_assert (tp_proxy_prepare_finish (test->conn, test->prepare_result,
214 &error));
215 g_assert_no_error (error);
216 g_object_unref (test->prepare_result);
217 test->prepare_result = NULL;
218
219 g_assert (tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE));
220 g_assert (!tp_proxy_is_prepared (test->conn,
221 TP_CONNECTION_FEATURE_CONNECTED));
222 g_assert_cmpuint (tp_connection_get_self_handle (test->conn), ==, 0);
223 g_assert_cmpint (tp_connection_get_status (test->conn, NULL), ==,
224 TP_CONNECTION_STATUS_DISCONNECTED);
225
226 g_assert_cmpstr (tp_connection_get_cm_name (test->conn), ==,
227 "simple");
228 g_assert_cmpstr (tp_connection_get_protocol_name (test->conn), ==,
229 "simple-protocol");
230
231 g_object_get (test->conn,
232 "cm-name", &cm_name,
233 "protocol-name", &protocol_name,
234 NULL);
235 g_assert_cmpstr (cm_name, ==, "simple");
236 g_assert_cmpstr (protocol_name, ==, "simple-protocol");
237 g_free (cm_name);
238 g_free (protocol_name);
239
240 tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL);
241
242 tp_proxy_prepare_async (test->conn, features, connection_prepared_cb, test);
243
244 while (test->prepare_result == NULL)
245 g_main_context_iteration (NULL, TRUE);
246
247 g_assert (tp_proxy_prepare_finish (test->conn, test->prepare_result,
248 &error));
249 g_assert_no_error (error);
250 g_object_unref (test->prepare_result);
251 test->prepare_result = NULL;
252
253 g_assert (tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE));
254 g_assert (tp_proxy_is_prepared (test->conn,
255 TP_CONNECTION_FEATURE_CONNECTED));
256 g_assert (tp_proxy_is_prepared (test->conn,
257 TP_CONNECTION_FEATURE_CAPABILITIES));
258 g_assert_cmpuint (tp_connection_get_self_handle (test->conn), !=, 0);
259 g_assert_cmpint (tp_connection_get_status (test->conn, &reason), ==,
260 TP_CONNECTION_STATUS_CONNECTED);
261 g_assert_cmpint (reason, ==, TP_CONNECTION_STATUS_REASON_REQUESTED);
262
263 caps = tp_connection_get_capabilities (test->conn);
264 g_assert (caps != NULL);
265 classes = tp_capabilities_get_channel_classes (caps);
266 g_assert (classes != NULL);
267 g_assert_cmpint (classes->len, ==, 0);
268 }
269
270 static void
test_fail_to_prepare(Test * test,gconstpointer nil G_GNUC_UNUSED)271 test_fail_to_prepare (Test *test,
272 gconstpointer nil G_GNUC_UNUSED)
273 {
274 GError *error = NULL;
275 GQuark features[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 };
276 const GHashTable *asv;
277
278 test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path,
279 &error);
280 g_assert (test->conn != NULL);
281 g_assert_no_error (error);
282
283 g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE));
284 g_assert (!tp_proxy_is_prepared (test->conn,
285 TP_CONNECTION_FEATURE_CONNECTED));
286
287 tp_proxy_prepare_async (test->conn, NULL, connection_prepared_cb, test);
288 tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL);
289 tp_proxy_invalidate ((TpProxy *) test->conn, &invalidated_for_test);
290 /* this is not synchronous */
291 g_assert (test->prepare_result == NULL);
292 g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE));
293
294 while (test->prepare_result == NULL)
295 g_main_context_iteration (NULL, TRUE);
296
297 g_assert (!tp_proxy_prepare_finish (test->conn, test->prepare_result,
298 &error));
299 g_assert_error (error, TP_ERROR, TP_ERROR_PERMISSION_DENIED);
300 g_clear_error (&error);
301 g_object_unref (test->prepare_result);
302 test->prepare_result = NULL;
303
304 g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE));
305 g_assert (!tp_proxy_is_prepared (test->conn,
306 TP_CONNECTION_FEATURE_CONNECTED));
307
308 /* it's not synchronous even if we were already invalidated */
309 tp_proxy_prepare_async (test->conn, features, connection_prepared_cb, test);
310 g_assert (test->prepare_result == NULL);
311
312 while (test->prepare_result == NULL)
313 g_main_context_iteration (NULL, TRUE);
314
315 g_assert (!tp_proxy_prepare_finish (test->conn, test->prepare_result,
316 &error));
317 g_assert_error (error, TP_ERROR, TP_ERROR_PERMISSION_DENIED);
318 g_clear_error (&error);
319 g_object_unref (test->prepare_result);
320 test->prepare_result = NULL;
321
322 g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE));
323 g_assert (!tp_proxy_is_prepared (test->conn,
324 TP_CONNECTION_FEATURE_CONNECTED));
325
326 g_assert_cmpstr (tp_connection_get_detailed_error (test->conn, NULL), ==,
327 TP_ERROR_STR_PERMISSION_DENIED);
328 g_assert_cmpstr (tp_connection_get_detailed_error (test->conn, &asv), ==,
329 TP_ERROR_STR_PERMISSION_DENIED);
330 g_assert (asv != NULL);
331 }
332
333 static void
test_call_when_ready(Test * test,gconstpointer nil G_GNUC_UNUSED)334 test_call_when_ready (Test *test,
335 gconstpointer nil G_GNUC_UNUSED)
336 {
337 GError *error = NULL;
338
339 test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path,
340 &error);
341 g_assert (test->conn != NULL);
342 g_assert_no_error (error);
343
344 tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL);
345
346 tp_connection_call_when_ready (test->conn, conn_ready, test);
347
348 while (!test->cwr_ready)
349 g_main_context_iteration (NULL, TRUE);
350
351 g_assert_no_error (test->cwr_error);
352
353 /* Connection already ready here, so we are called back synchronously */
354
355 test->cwr_ready = FALSE;
356 test->cwr_error = NULL;
357 tp_connection_call_when_ready (test->conn, conn_ready, test);
358 g_assert_cmpint (test->cwr_ready, ==, TRUE);
359 g_assert_no_error (test->cwr_error);
360 }
361
362 static void
test_call_when_invalid(Test * test,gconstpointer nil G_GNUC_UNUSED)363 test_call_when_invalid (Test *test,
364 gconstpointer nil G_GNUC_UNUSED)
365 {
366 GError *error = NULL;
367
368 test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path,
369 &error);
370 g_assert (test->conn != NULL);
371 g_assert_no_error (error);
372
373 /* Connection becomes invalid, so we are called back synchronously */
374
375 tp_connection_call_when_ready (test->conn, conn_ready, test);
376 tp_proxy_invalidate ((TpProxy *) test->conn, &invalidated_for_test);
377 g_assert_cmpint (test->cwr_ready, ==, TRUE);
378 g_assert_error (test->cwr_error, invalidated_for_test.domain,
379 invalidated_for_test.code);
380 g_assert_cmpstr (test->cwr_error->message, ==, invalidated_for_test.message);
381 g_clear_error (&test->cwr_error);
382
383 /* Connection already invalid, so we are called back synchronously */
384
385 test->cwr_ready = FALSE;
386 test->cwr_error = NULL;
387 tp_connection_call_when_ready (test->conn, conn_ready, test);
388 g_assert (test->cwr_ready);
389 g_assert_error (test->cwr_error, invalidated_for_test.domain,
390 invalidated_for_test.code);
391 g_assert_cmpstr (test->cwr_error->message, ==, invalidated_for_test.message);
392 g_error_free (test->cwr_error);
393 test->cwr_error = NULL;
394 }
395
396 static void
test_object_path(Test * test,gconstpointer nil G_GNUC_UNUSED)397 test_object_path (Test *test,
398 gconstpointer nil G_GNUC_UNUSED)
399 {
400 const gchar *invalid_path = TP_CONN_OBJECT_PATH_BASE "invalid";
401 const gchar *invalid_name = TP_CONN_BUS_NAME_BASE "invalid";
402 TpConnection *connection;
403 GError *error = NULL;
404
405 test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path,
406 &error);
407 g_assert (test->conn != NULL);
408 g_assert_no_error (error);
409
410 tp_tests_proxy_run_until_prepared (test->conn, NULL);
411 g_assert_cmpstr (tp_connection_get_cm_name (test->conn), ==,
412 "simple");
413 g_assert_cmpstr (tp_connection_get_protocol_name (test->conn), ==,
414 "simple-protocol");
415
416 /* Register the same connection with an invalid object path */
417 tp_dbus_daemon_register_object (test->dbus, invalid_path, test->service_conn);
418 tp_dbus_daemon_request_name (test->dbus, invalid_name, FALSE, &error);
419 g_assert_no_error (error);
420
421 /* Create a TpConnection for that path, it return invalidated connection */
422 connection = tp_connection_new (test->dbus, NULL, invalid_path, &error);
423 g_assert (connection == NULL);
424 g_assert_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_OBJECT_PATH);
425 g_clear_error (&error);
426 }
427
428 int
main(int argc,char ** argv)429 main (int argc,
430 char **argv)
431 {
432 tp_tests_init (&argc, &argv);
433
434 g_test_add ("/conn/prepare", Test, NULL, setup, test_prepare, teardown);
435 g_test_add ("/conn/fail_to_prepare", Test, NULL, setup, test_fail_to_prepare,
436 teardown);
437 g_test_add ("/conn/run_until_invalid", Test, NULL, setup,
438 test_run_until_invalid, teardown);
439 g_test_add ("/conn/run_until_ready", Test, NULL, setup,
440 test_run_until_ready, teardown);
441 g_test_add ("/conn/call_when_ready", Test, NULL, setup,
442 test_call_when_ready, teardown);
443 g_test_add ("/conn/call_when_invalid", Test, NULL, setup,
444 test_call_when_invalid, teardown);
445 g_test_add ("/conn/object_path", Test, NULL, setup,
446 test_object_path, teardown);
447
448 return tp_tests_run_with_bus ();
449 }
450