1 /* Feature test for https://bugs.freedesktop.org/show_bug.cgi?id=27835
2 *
3 * Copyright © 2007-2010 Collabora Ltd. <http://www.collabora.co.uk/>
4 * Copyright © 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 <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 /* an almost-no-op subclass... */
26 typedef TpTestsSimpleConnection InterestedConnection;
27 typedef TpTestsSimpleConnectionClass InterestedConnectionClass;
28
29 static GType interested_connection_get_type (void);
30
G_DEFINE_TYPE_WITH_CODE(InterestedConnection,interested_connection,TP_TESTS_TYPE_SIMPLE_CONNECTION,G_STMT_START{ } G_STMT_END)31 G_DEFINE_TYPE_WITH_CODE (InterestedConnection,
32 interested_connection,
33 TP_TESTS_TYPE_SIMPLE_CONNECTION,
34 G_STMT_START { } G_STMT_END)
35
36 /* Lord Pearson of Rannoch: My Lords, I beg leave to ask the Question
37 * standing in my name on the Order Paper. In doing so, I declare an
38 * interest as patron of the British Register of Chinese Herbal Medicine.
39 * -- Hansard, 2010-02-01 */
40 #define SUPPORTED_TOKEN "com.example.rannoch/ChineseHerbalMedicine"
41
42 /* Lord Hoyle: My Lords, in thanking my noble friend for his Answer, I declare
43 * an interest as the chairman and now president of Warrington Wolves Rugby
44 * League Club. -- Hansard, 2010-01-11
45 */
46 #define UNSUPPORTED_TOKEN "org.example.Warrington/Wolves"
47
48 static void
49 interested_connection_init (InterestedConnection *self G_GNUC_UNUSED)
50 {
51 }
52
53 static void
interested_connection_constructed(GObject * object)54 interested_connection_constructed (GObject *object)
55 {
56 TpBaseConnection *base = (TpBaseConnection *) object;
57 void (*chain_up) (GObject *) =
58 ((GObjectClass *) interested_connection_parent_class)->constructed;
59
60 if (chain_up != NULL)
61 chain_up (object);
62
63 tp_base_connection_add_possible_client_interest (base,
64 TP_IFACE_QUARK_CONNECTION_INTERFACE_LOCATION);
65 tp_base_connection_add_possible_client_interest (base,
66 g_quark_from_static_string (SUPPORTED_TOKEN));
67 }
68
69 static void
interested_connection_class_init(InterestedConnectionClass * cls)70 interested_connection_class_init (InterestedConnectionClass *cls)
71 {
72 GObjectClass *object_class = (GObjectClass *) cls;
73
74 object_class->constructed = interested_connection_constructed;
75 }
76
77 typedef struct {
78 TpDBusDaemon *dbus;
79 DBusConnection *client_libdbus;
80 DBusGConnection *client_dbusglib;
81 TpDBusDaemon *client_bus;
82 TpTestsSimpleConnection *service_conn;
83 TpBaseConnection *service_conn_as_base;
84 gchar *conn_name;
85 gchar *conn_path;
86 TpConnection *conn;
87
88 gboolean cwr_ready;
89 GError *cwr_error /* initialized in setup */;
90
91 GAsyncResult *prepare_result;
92
93 GPtrArray *log;
94 } Test;
95
96 static void
connection_prepared_cb(GObject * object,GAsyncResult * res,gpointer user_data)97 connection_prepared_cb (GObject *object,
98 GAsyncResult *res,
99 gpointer user_data)
100 {
101 Test *test = user_data;
102
103 g_message ("%p prepared", object);
104 g_assert (test->prepare_result == NULL);
105 test->prepare_result = g_object_ref (res);
106 }
107
108 static void
interested_cb(TpBaseConnection * unused G_GNUC_UNUSED,const gchar * iface,Test * test)109 interested_cb (TpBaseConnection *unused G_GNUC_UNUSED,
110 const gchar *iface,
111 Test *test)
112 {
113 g_ptr_array_add (test->log, g_strdup_printf ("interested in %s", iface));
114 }
115
116 static void
location_interested_cb(TpBaseConnection * unused G_GNUC_UNUSED,const gchar * iface,Test * test)117 location_interested_cb (TpBaseConnection *unused G_GNUC_UNUSED,
118 const gchar *iface,
119 Test *test)
120 {
121 g_assert_cmpstr (iface, ==, TP_IFACE_CONNECTION_INTERFACE_LOCATION);
122
123 g_ptr_array_add (test->log, g_strdup ("Location interested"));
124 }
125
126 static void
uninterested_cb(TpBaseConnection * unused G_GNUC_UNUSED,const gchar * iface,Test * test)127 uninterested_cb (TpBaseConnection *unused G_GNUC_UNUSED,
128 const gchar *iface,
129 Test *test)
130 {
131 g_ptr_array_add (test->log, g_strdup_printf ("uninterested in %s", iface));
132 }
133
134 static void
location_uninterested_cb(TpBaseConnection * unused G_GNUC_UNUSED,const gchar * iface,Test * test)135 location_uninterested_cb (TpBaseConnection *unused G_GNUC_UNUSED,
136 const gchar *iface,
137 Test *test)
138 {
139 g_assert_cmpstr (iface, ==, TP_IFACE_CONNECTION_INTERFACE_LOCATION);
140
141 g_ptr_array_add (test->log, g_strdup ("Location uninterested"));
142 }
143
144 static void
setup(Test * test,gconstpointer data)145 setup (Test *test,
146 gconstpointer data)
147 {
148 GError *error = NULL;
149 GQuark features[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 };
150
151 tp_debug_set_flags ("all");
152 test->dbus = tp_tests_dbus_daemon_dup_or_die ();
153
154 test->client_libdbus = dbus_bus_get_private (DBUS_BUS_STARTER, NULL);
155 g_assert (test->client_libdbus != NULL);
156 dbus_connection_setup_with_g_main (test->client_libdbus, NULL);
157 dbus_connection_set_exit_on_disconnect (test->client_libdbus, FALSE);
158 test->client_dbusglib = dbus_connection_get_g_connection (
159 test->client_libdbus);
160 dbus_g_connection_ref (test->client_dbusglib);
161 test->client_bus = tp_dbus_daemon_new (test->client_dbusglib);
162 g_assert (test->client_bus != NULL);
163
164 test->service_conn = tp_tests_object_new_static_class (
165 interested_connection_get_type (),
166 "account", "me@example.com",
167 "protocol", "simple-protocol",
168 NULL);
169 test->service_conn_as_base = TP_BASE_CONNECTION (test->service_conn);
170 g_assert (test->service_conn != NULL);
171 g_assert (test->service_conn_as_base != NULL);
172
173 g_assert (tp_base_connection_register (test->service_conn_as_base, "simple",
174 &test->conn_name, &test->conn_path, &error));
175 g_assert_no_error (error);
176
177 test->cwr_ready = FALSE;
178 test->cwr_error = NULL;
179
180 test->conn = tp_connection_new (test->client_bus, test->conn_name,
181 test->conn_path, &error);
182 g_assert (test->conn != NULL);
183 g_assert_no_error (error);
184
185 tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL);
186
187 g_assert (!tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE));
188 g_assert (!tp_proxy_is_prepared (test->conn,
189 TP_CONNECTION_FEATURE_CONNECTED));
190
191 tp_proxy_prepare_async (test->conn, features, connection_prepared_cb, test);
192 g_assert (test->prepare_result == NULL);
193
194 while (test->prepare_result == NULL)
195 g_main_context_iteration (NULL, TRUE);
196
197 g_assert (tp_proxy_prepare_finish (test->conn, test->prepare_result,
198 &error));
199 g_assert_no_error (error);
200 g_object_unref (test->prepare_result);
201 test->prepare_result = NULL;
202
203 test->log = g_ptr_array_new_with_free_func (g_free);
204
205 g_signal_connect (test->service_conn,
206 "clients-interested", G_CALLBACK (interested_cb), test);
207 g_signal_connect (test->service_conn,
208 "clients-interested::" TP_IFACE_CONNECTION_INTERFACE_LOCATION,
209 G_CALLBACK (location_interested_cb), test);
210
211 g_signal_connect (test->service_conn,
212 "clients-uninterested", G_CALLBACK (uninterested_cb), test);
213 g_signal_connect (test->service_conn,
214 "clients-uninterested::" TP_IFACE_CONNECTION_INTERFACE_LOCATION,
215 G_CALLBACK (location_uninterested_cb), test);
216 }
217
218 static void
teardown(Test * test,gconstpointer data)219 teardown (Test *test,
220 gconstpointer data)
221 {
222 TpConnection *conn;
223 GError *error = NULL;
224
225 if (test->conn != NULL)
226 {
227 g_object_unref (test->conn);
228 test->conn = NULL;
229 }
230
231 /* disconnect the connection so we don't leak it */
232 conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path,
233 &error);
234 g_assert (conn != NULL);
235 g_assert_no_error (error);
236
237 tp_tests_connection_assert_disconnect_succeeds (conn);
238
239 g_assert (!tp_connection_run_until_ready (conn, FALSE, &error, NULL));
240 g_assert_error (error, TP_ERROR, TP_ERROR_CANCELLED);
241 g_clear_error (&error);
242
243 test->service_conn_as_base = NULL;
244 g_object_unref (test->service_conn);
245 g_free (test->conn_name);
246 g_free (test->conn_path);
247
248 g_object_unref (test->dbus);
249 test->dbus = NULL;
250 g_object_unref (test->client_bus);
251 test->client_bus = NULL;
252
253 dbus_g_connection_unref (test->client_dbusglib);
254 dbus_connection_close (test->client_libdbus);
255 dbus_connection_unref (test->client_libdbus);
256
257 g_ptr_array_unref (test->log);
258 }
259
260 static void
test_interested_client(Test * test,gconstpointer nil G_GNUC_UNUSED)261 test_interested_client (Test *test,
262 gconstpointer nil G_GNUC_UNUSED)
263 {
264 guint i;
265
266 tp_connection_add_client_interest_by_id (test->conn,
267 TP_IFACE_QUARK_CONNECTION_INTERFACE_LOCATION);
268 tp_connection_add_client_interest_by_id (test->conn,
269 TP_IFACE_QUARK_CONNECTION_INTERFACE_AVATARS);
270
271 /* run until (after) the AddClientInterest calls have gone out */
272 tp_tests_proxy_run_until_dbus_queue_processed (test->client_bus);
273
274 /* we auto-release the Location client interest by disposing the client
275 * connection */
276 g_object_run_dispose ((GObject *) test->conn);
277 g_object_unref (test->conn);
278 test->conn = NULL;
279
280 /* run until (after) the RemoveClientInterest call has gone out */
281 tp_tests_proxy_run_until_dbus_queue_processed (test->client_bus);
282
283 /* then, run until (after) the CM should have processed both ACI and RCI */
284 tp_tests_proxy_run_until_dbus_queue_processed (test->dbus);
285
286 i = 0;
287 g_assert_cmpuint (test->log->len, >, i);
288 g_assert_cmpstr (g_ptr_array_index (test->log, i), ==,
289 "interested in " TP_IFACE_CONNECTION_INTERFACE_LOCATION);
290
291 i++;
292 g_assert_cmpuint (test->log->len, >, i);
293 g_assert_cmpstr (g_ptr_array_index (test->log, i), ==,
294 "Location interested");
295
296 i++;
297 g_assert_cmpuint (test->log->len, >, i);
298 g_assert_cmpstr (g_ptr_array_index (test->log, i), ==,
299 "uninterested in " TP_IFACE_CONNECTION_INTERFACE_LOCATION);
300
301 i++;
302 g_assert_cmpuint (test->log->len, >, i);
303 g_assert_cmpstr (g_ptr_array_index (test->log, i), ==,
304 "Location uninterested");
305
306 i++;
307 g_assert_cmpuint (test->log->len, ==, i);
308 }
309
310 static void
test_interest(Test * test,gconstpointer nil G_GNUC_UNUSED)311 test_interest (Test *test,
312 gconstpointer nil G_GNUC_UNUSED)
313 {
314 static const gchar * telepathy[] = {
315 TP_IFACE_CONNECTION_INTERFACE_LOCATION,
316 TP_IFACE_CONNECTION_INTERFACE_AVATARS,
317 NULL
318 };
319 static const gchar * hansard[] = {
320 SUPPORTED_TOKEN,
321 UNSUPPORTED_TOKEN,
322 NULL
323 };
324 GError *error = NULL;
325 guint i;
326
327 tp_cli_connection_run_add_client_interest (test->conn, -1, telepathy, &error,
328 NULL);
329 g_assert_no_error (error);
330
331 tp_cli_connection_run_add_client_interest (test->conn, -1, hansard, &error,
332 NULL);
333 g_assert_no_error (error);
334
335 tp_cli_connection_run_add_client_interest (test->conn, -1, telepathy, &error,
336 NULL);
337 g_assert_no_error (error);
338
339 tp_cli_connection_run_remove_client_interest (test->conn, -1, telepathy,
340 &error, NULL);
341 g_assert_no_error (error);
342
343 tp_cli_connection_run_remove_client_interest (test->conn, -1, hansard,
344 &error, NULL);
345 g_assert_no_error (error);
346
347 /* we auto-release the Location client interest by dropping the client
348 * connection */
349 dbus_connection_flush (test->client_libdbus);
350 dbus_connection_close (test->client_libdbus);
351
352 while (test->log->len < 6)
353 g_main_context_iteration (NULL, TRUE);
354
355 i = 0;
356 g_assert_cmpuint (test->log->len, >, i);
357 g_assert_cmpstr (g_ptr_array_index (test->log, i), ==,
358 "interested in " TP_IFACE_CONNECTION_INTERFACE_LOCATION);
359
360 i++;
361 g_assert_cmpuint (test->log->len, >, i);
362 g_assert_cmpstr (g_ptr_array_index (test->log, i), ==,
363 "Location interested");
364
365 i++;
366 g_assert_cmpuint (test->log->len, >, i);
367 g_assert_cmpstr (g_ptr_array_index (test->log, i), ==,
368 "interested in " SUPPORTED_TOKEN);
369
370 i++;
371 g_assert_cmpuint (test->log->len, >, i);
372 g_assert_cmpstr (g_ptr_array_index (test->log, i), ==,
373 "uninterested in " SUPPORTED_TOKEN);
374
375 i++;
376 g_assert_cmpuint (test->log->len, >, i);
377 g_assert_cmpstr (g_ptr_array_index (test->log, i), ==,
378 "uninterested in " TP_IFACE_CONNECTION_INTERFACE_LOCATION);
379
380 i++;
381 g_assert_cmpuint (test->log->len, >, i);
382 g_assert_cmpstr (g_ptr_array_index (test->log, i), ==,
383 "Location uninterested");
384
385 i++;
386 g_assert_cmpuint (test->log->len, ==, i);
387 }
388
389 int
main(int argc,char ** argv)390 main (int argc,
391 char **argv)
392 {
393 tp_tests_init (&argc, &argv);
394
395 g_test_add ("/conn/interest", Test, NULL, setup, test_interest, teardown);
396 g_test_add ("/conn/interested-client", Test, NULL, setup,
397 test_interested_client, teardown);
398
399 return tp_tests_run_with_bus ();
400 }
401