1 /* GLib testing framework examples and tests
2 *
3 * Copyright (C) 2008-2010 Red Hat, Inc.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 *
18 * Author: David Zeuthen <davidz@redhat.com>
19 */
20
21 #include <gio/gio.h>
22 #include <unistd.h>
23
24 #include "gdbus-tests.h"
25
26 /* all tests rely on a shared mainloop */
27 static GMainLoop *loop;
28
29 /* ---------------------------------------------------------------------------------------------------- */
30 /* Test that g_bus_own_name() works correctly */
31 /* ---------------------------------------------------------------------------------------------------- */
32
33 typedef struct
34 {
35 GMainLoop *loop;
36 gboolean expect_null_connection;
37 guint num_bus_acquired;
38 guint num_acquired;
39 guint num_lost;
40 guint num_free_func;
41 } OwnNameData;
42
43 static void
own_name_data_free_func(OwnNameData * data)44 own_name_data_free_func (OwnNameData *data)
45 {
46 data->num_free_func++;
47 g_main_loop_quit (loop);
48 }
49
50 static void
bus_acquired_handler(GDBusConnection * connection,const gchar * name,gpointer user_data)51 bus_acquired_handler (GDBusConnection *connection,
52 const gchar *name,
53 gpointer user_data)
54 {
55 OwnNameData *data = user_data;
56 g_dbus_connection_set_exit_on_close (connection, FALSE);
57 data->num_bus_acquired += 1;
58 g_main_loop_quit (loop);
59 }
60
61 static void
name_acquired_handler(GDBusConnection * connection,const gchar * name,gpointer user_data)62 name_acquired_handler (GDBusConnection *connection,
63 const gchar *name,
64 gpointer user_data)
65 {
66 OwnNameData *data = user_data;
67 data->num_acquired += 1;
68 g_main_loop_quit (loop);
69 }
70
71 static void
name_lost_handler(GDBusConnection * connection,const gchar * name,gpointer user_data)72 name_lost_handler (GDBusConnection *connection,
73 const gchar *name,
74 gpointer user_data)
75 {
76 OwnNameData *data = user_data;
77 if (data->expect_null_connection)
78 {
79 g_assert (connection == NULL);
80 }
81 else
82 {
83 g_assert (connection != NULL);
84 g_dbus_connection_set_exit_on_close (connection, FALSE);
85 }
86 data->num_lost += 1;
87 g_main_loop_quit (loop);
88 }
89
90 static void
test_bus_own_name(void)91 test_bus_own_name (void)
92 {
93 guint id;
94 guint id2;
95 OwnNameData data;
96 OwnNameData data2;
97 const gchar *name;
98 GDBusConnection *c;
99 GError *error;
100 gboolean name_has_owner_reply;
101 GDBusConnection *c2;
102 GVariant *result;
103
104 error = NULL;
105 name = "org.gtk.GDBus.Name1";
106
107 /*
108 * First check that name_lost_handler() is invoked if there is no bus.
109 *
110 * Also make sure name_lost_handler() isn't invoked when unowning the name.
111 */
112 data.num_bus_acquired = 0;
113 data.num_free_func = 0;
114 data.num_acquired = 0;
115 data.num_lost = 0;
116 data.expect_null_connection = TRUE;
117 id = g_bus_own_name (G_BUS_TYPE_SESSION,
118 name,
119 G_BUS_NAME_OWNER_FLAGS_NONE,
120 bus_acquired_handler,
121 name_acquired_handler,
122 name_lost_handler,
123 &data,
124 (GDestroyNotify) own_name_data_free_func);
125 g_assert_cmpint (data.num_bus_acquired, ==, 0);
126 g_assert_cmpint (data.num_acquired, ==, 0);
127 g_assert_cmpint (data.num_lost, ==, 0);
128 g_main_loop_run (loop);
129 g_assert_cmpint (data.num_bus_acquired, ==, 0);
130 g_assert_cmpint (data.num_acquired, ==, 0);
131 g_assert_cmpint (data.num_lost, ==, 1);
132 g_bus_unown_name (id);
133 g_assert_cmpint (data.num_acquired, ==, 0);
134 g_assert_cmpint (data.num_lost, ==, 1);
135 g_assert_cmpint (data.num_free_func, ==, 1);
136
137 /*
138 * Bring up a bus, then own a name and check bus_acquired_handler() then name_acquired_handler() is invoked.
139 */
140 session_bus_up ();
141 data.num_bus_acquired = 0;
142 data.num_acquired = 0;
143 data.num_lost = 0;
144 data.expect_null_connection = FALSE;
145 id = g_bus_own_name (G_BUS_TYPE_SESSION,
146 name,
147 G_BUS_NAME_OWNER_FLAGS_NONE,
148 bus_acquired_handler,
149 name_acquired_handler,
150 name_lost_handler,
151 &data,
152 (GDestroyNotify) own_name_data_free_func);
153 g_assert_cmpint (data.num_bus_acquired, ==, 0);
154 g_assert_cmpint (data.num_acquired, ==, 0);
155 g_assert_cmpint (data.num_lost, ==, 0);
156 g_main_loop_run (loop);
157 g_assert_cmpint (data.num_bus_acquired, ==, 1);
158 g_assert_cmpint (data.num_acquired, ==, 0);
159 g_assert_cmpint (data.num_lost, ==, 0);
160 g_main_loop_run (loop);
161 g_assert_cmpint (data.num_bus_acquired, ==, 1);
162 g_assert_cmpint (data.num_acquired, ==, 1);
163 g_assert_cmpint (data.num_lost, ==, 0);
164
165 /*
166 * Check that the name was actually acquired.
167 */
168 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
169 g_assert (c != NULL);
170 g_assert (!g_dbus_connection_is_closed (c));
171 result = g_dbus_connection_call_sync (c,
172 "org.freedesktop.DBus", /* bus name */
173 "/org/freedesktop/DBus", /* object path */
174 "org.freedesktop.DBus", /* interface name */
175 "NameHasOwner", /* method name */
176 g_variant_new ("(s)", name),
177 G_VARIANT_TYPE ("(b)"),
178 G_DBUS_CALL_FLAGS_NONE,
179 -1,
180 NULL,
181 &error);
182 g_assert_no_error (error);
183 g_assert (result != NULL);
184 g_variant_get (result, "(b)", &name_has_owner_reply);
185 g_assert (name_has_owner_reply);
186 g_variant_unref (result);
187
188 /*
189 * Stop owning the name - this should invoke our free func
190 */
191 g_bus_unown_name (id);
192 g_assert_cmpint (data.num_free_func, ==, 2);
193
194 /*
195 * Check that the name was actually released.
196 */
197 result = g_dbus_connection_call_sync (c,
198 "org.freedesktop.DBus", /* bus name */
199 "/org/freedesktop/DBus", /* object path */
200 "org.freedesktop.DBus", /* interface name */
201 "NameHasOwner", /* method name */
202 g_variant_new ("(s)", name),
203 G_VARIANT_TYPE ("(b)"),
204 G_DBUS_CALL_FLAGS_NONE,
205 -1,
206 NULL,
207 &error);
208 g_assert_no_error (error);
209 g_assert (result != NULL);
210 g_variant_get (result, "(b)", &name_has_owner_reply);
211 g_assert (!name_has_owner_reply);
212 g_variant_unref (result);
213
214 /* Now try owning the name and then immediately decide to unown the name */
215 g_assert_cmpint (data.num_bus_acquired, ==, 1);
216 g_assert_cmpint (data.num_acquired, ==, 1);
217 g_assert_cmpint (data.num_lost, ==, 0);
218 g_assert_cmpint (data.num_free_func, ==, 2);
219 id = g_bus_own_name (G_BUS_TYPE_SESSION,
220 name,
221 G_BUS_NAME_OWNER_FLAGS_NONE,
222 bus_acquired_handler,
223 name_acquired_handler,
224 name_lost_handler,
225 &data,
226 (GDestroyNotify) own_name_data_free_func);
227 g_assert_cmpint (data.num_bus_acquired, ==, 1);
228 g_assert_cmpint (data.num_acquired, ==, 1);
229 g_assert_cmpint (data.num_lost, ==, 0);
230 g_assert_cmpint (data.num_free_func, ==, 2);
231 g_bus_unown_name (id);
232 g_assert_cmpint (data.num_bus_acquired, ==, 1);
233 g_assert_cmpint (data.num_acquired, ==, 1);
234 g_assert_cmpint (data.num_lost, ==, 0);
235 g_assert_cmpint (data.num_free_func, ==, 2);
236 g_main_loop_run (loop); /* the GDestroyNotify is called in idle because the bus is acquired in idle */
237 g_assert_cmpint (data.num_free_func, ==, 3);
238
239 /*
240 * Own the name again.
241 */
242 data.num_bus_acquired = 0;
243 data.num_acquired = 0;
244 data.num_lost = 0;
245 data.expect_null_connection = FALSE;
246 id = g_bus_own_name_with_closures (G_BUS_TYPE_SESSION,
247 name,
248 G_BUS_NAME_OWNER_FLAGS_NONE,
249 g_cclosure_new (G_CALLBACK (bus_acquired_handler),
250 &data,
251 NULL),
252 g_cclosure_new (G_CALLBACK (name_acquired_handler),
253 &data,
254 NULL),
255 g_cclosure_new (G_CALLBACK (name_lost_handler),
256 &data,
257 (GClosureNotify) own_name_data_free_func));
258 g_assert_cmpint (data.num_bus_acquired, ==, 0);
259 g_assert_cmpint (data.num_acquired, ==, 0);
260 g_assert_cmpint (data.num_lost, ==, 0);
261 g_main_loop_run (loop);
262 g_assert_cmpint (data.num_bus_acquired, ==, 1);
263 g_assert_cmpint (data.num_acquired, ==, 0);
264 g_assert_cmpint (data.num_lost, ==, 0);
265 g_main_loop_run (loop);
266 g_assert_cmpint (data.num_bus_acquired, ==, 1);
267 g_assert_cmpint (data.num_acquired, ==, 1);
268 g_assert_cmpint (data.num_lost, ==, 0);
269
270 /*
271 * Try owning the name with another object on the same connection - this should
272 * fail because we already own the name.
273 */
274 data2.num_free_func = 0;
275 data2.num_bus_acquired = 0;
276 data2.num_acquired = 0;
277 data2.num_lost = 0;
278 data2.expect_null_connection = FALSE;
279 id2 = g_bus_own_name (G_BUS_TYPE_SESSION,
280 name,
281 G_BUS_NAME_OWNER_FLAGS_NONE,
282 bus_acquired_handler,
283 name_acquired_handler,
284 name_lost_handler,
285 &data2,
286 (GDestroyNotify) own_name_data_free_func);
287 g_assert_cmpint (data2.num_bus_acquired, ==, 0);
288 g_assert_cmpint (data2.num_acquired, ==, 0);
289 g_assert_cmpint (data2.num_lost, ==, 0);
290 g_main_loop_run (loop);
291 g_assert_cmpint (data2.num_bus_acquired, ==, 1);
292 g_assert_cmpint (data2.num_acquired, ==, 0);
293 g_assert_cmpint (data2.num_lost, ==, 0);
294 g_main_loop_run (loop);
295 g_assert_cmpint (data2.num_bus_acquired, ==, 1);
296 g_assert_cmpint (data2.num_acquired, ==, 0);
297 g_assert_cmpint (data2.num_lost, ==, 1);
298 g_bus_unown_name (id2);
299 g_assert_cmpint (data2.num_bus_acquired, ==, 1);
300 g_assert_cmpint (data2.num_acquired, ==, 0);
301 g_assert_cmpint (data2.num_lost, ==, 1);
302 g_assert_cmpint (data2.num_free_func, ==, 1);
303
304 /*
305 * Create a secondary (e.g. private) connection and try owning the name on that
306 * connection. This should fail both with and without _REPLACE because we
307 * didn't specify ALLOW_REPLACEMENT.
308 */
309 c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
310 g_assert (c2 != NULL);
311 g_assert (!g_dbus_connection_is_closed (c2));
312 /* first without _REPLACE */
313 data2.num_bus_acquired = 0;
314 data2.num_acquired = 0;
315 data2.num_lost = 0;
316 data2.expect_null_connection = FALSE;
317 data2.num_free_func = 0;
318 id2 = g_bus_own_name_on_connection (c2,
319 name,
320 G_BUS_NAME_OWNER_FLAGS_NONE,
321 name_acquired_handler,
322 name_lost_handler,
323 &data2,
324 (GDestroyNotify) own_name_data_free_func);
325 g_assert_cmpint (data2.num_bus_acquired, ==, 0);
326 g_assert_cmpint (data2.num_acquired, ==, 0);
327 g_assert_cmpint (data2.num_lost, ==, 0);
328 g_main_loop_run (loop);
329 g_assert_cmpint (data2.num_bus_acquired, ==, 0);
330 g_assert_cmpint (data2.num_acquired, ==, 0);
331 g_assert_cmpint (data2.num_lost, ==, 1);
332 g_bus_unown_name (id2);
333 g_assert_cmpint (data2.num_bus_acquired, ==, 0);
334 g_assert_cmpint (data2.num_acquired, ==, 0);
335 g_assert_cmpint (data2.num_lost, ==, 1);
336 g_assert_cmpint (data2.num_free_func, ==, 1);
337 /* then with _REPLACE */
338 data2.num_bus_acquired = 0;
339 data2.num_acquired = 0;
340 data2.num_lost = 0;
341 data2.expect_null_connection = FALSE;
342 data2.num_free_func = 0;
343 id2 = g_bus_own_name_on_connection (c2,
344 name,
345 G_BUS_NAME_OWNER_FLAGS_REPLACE,
346 name_acquired_handler,
347 name_lost_handler,
348 &data2,
349 (GDestroyNotify) own_name_data_free_func);
350 g_assert_cmpint (data2.num_bus_acquired, ==, 0);
351 g_assert_cmpint (data2.num_acquired, ==, 0);
352 g_assert_cmpint (data2.num_lost, ==, 0);
353 g_main_loop_run (loop);
354 g_assert_cmpint (data2.num_bus_acquired, ==, 0);
355 g_assert_cmpint (data2.num_acquired, ==, 0);
356 g_assert_cmpint (data2.num_lost, ==, 1);
357 g_bus_unown_name (id2);
358 g_assert_cmpint (data2.num_bus_acquired, ==, 0);
359 g_assert_cmpint (data2.num_acquired, ==, 0);
360 g_assert_cmpint (data2.num_lost, ==, 1);
361 g_assert_cmpint (data2.num_free_func, ==, 1);
362
363 /*
364 * Stop owning the name and grab it again with _ALLOW_REPLACEMENT.
365 */
366 data.expect_null_connection = FALSE;
367 g_bus_unown_name (id);
368 g_assert_cmpint (data.num_bus_acquired, ==, 1);
369 g_assert_cmpint (data.num_acquired, ==, 1);
370 g_assert_cmpint (data.num_free_func, ==, 4);
371 /* grab it again */
372 data.num_bus_acquired = 0;
373 data.num_acquired = 0;
374 data.num_lost = 0;
375 data.expect_null_connection = FALSE;
376 id = g_bus_own_name (G_BUS_TYPE_SESSION,
377 name,
378 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
379 bus_acquired_handler,
380 name_acquired_handler,
381 name_lost_handler,
382 &data,
383 (GDestroyNotify) own_name_data_free_func);
384 g_assert_cmpint (data.num_bus_acquired, ==, 0);
385 g_assert_cmpint (data.num_acquired, ==, 0);
386 g_assert_cmpint (data.num_lost, ==, 0);
387 g_main_loop_run (loop);
388 g_assert_cmpint (data.num_bus_acquired, ==, 1);
389 g_assert_cmpint (data.num_acquired, ==, 0);
390 g_assert_cmpint (data.num_lost, ==, 0);
391 g_main_loop_run (loop);
392 g_assert_cmpint (data.num_bus_acquired, ==, 1);
393 g_assert_cmpint (data.num_acquired, ==, 1);
394 g_assert_cmpint (data.num_lost, ==, 0);
395
396 /*
397 * Now try to grab the name from the secondary connection.
398 *
399 */
400 /* first without _REPLACE - this won't make us acquire the name */
401 data2.num_bus_acquired = 0;
402 data2.num_acquired = 0;
403 data2.num_lost = 0;
404 data2.expect_null_connection = FALSE;
405 data2.num_free_func = 0;
406 id2 = g_bus_own_name_on_connection (c2,
407 name,
408 G_BUS_NAME_OWNER_FLAGS_NONE,
409 name_acquired_handler,
410 name_lost_handler,
411 &data2,
412 (GDestroyNotify) own_name_data_free_func);
413 g_assert_cmpint (data2.num_bus_acquired, ==, 0);
414 g_assert_cmpint (data2.num_acquired, ==, 0);
415 g_assert_cmpint (data2.num_lost, ==, 0);
416 g_main_loop_run (loop);
417 g_assert_cmpint (data2.num_bus_acquired, ==, 0);
418 g_assert_cmpint (data2.num_acquired, ==, 0);
419 g_assert_cmpint (data2.num_lost, ==, 1);
420 g_bus_unown_name (id2);
421 g_assert_cmpint (data2.num_bus_acquired, ==, 0);
422 g_assert_cmpint (data2.num_acquired, ==, 0);
423 g_assert_cmpint (data2.num_lost, ==, 1);
424 g_assert_cmpint (data2.num_free_func, ==, 1);
425 /* then with _REPLACE - here we should acquire the name - e.g. owner should lose it
426 * and owner2 should acquire it */
427 data2.num_bus_acquired = 0;
428 data2.num_acquired = 0;
429 data2.num_lost = 0;
430 data2.expect_null_connection = FALSE;
431 data2.num_free_func = 0;
432 id2 = g_bus_own_name_on_connection (c2,
433 name,
434 G_BUS_NAME_OWNER_FLAGS_REPLACE,
435 name_acquired_handler,
436 name_lost_handler,
437 &data2,
438 (GDestroyNotify) own_name_data_free_func);
439 g_assert_cmpint (data.num_acquired, ==, 1);
440 g_assert_cmpint (data.num_lost, ==, 0);
441 g_assert_cmpint (data2.num_acquired, ==, 0);
442 g_assert_cmpint (data2.num_lost, ==, 0);
443 /* wait for handlers for both owner and owner2 to fire */
444 while (data.num_lost == 0 || data2.num_acquired == 0)
445 g_main_loop_run (loop);
446 g_assert_cmpint (data.num_acquired, ==, 1);
447 g_assert_cmpint (data.num_lost, ==, 1);
448 g_assert_cmpint (data2.num_acquired, ==, 1);
449 g_assert_cmpint (data2.num_lost, ==, 0);
450 g_assert_cmpint (data2.num_bus_acquired, ==, 0);
451 /* ok, make owner2 release the name - then wait for owner to automagically reacquire it */
452 g_bus_unown_name (id2);
453 g_assert_cmpint (data2.num_free_func, ==, 1);
454 g_main_loop_run (loop);
455 g_assert_cmpint (data.num_acquired, ==, 2);
456 g_assert_cmpint (data.num_lost, ==, 1);
457
458 /*
459 * Finally, nuke the bus and check name_lost_handler() is invoked.
460 *
461 */
462 data.expect_null_connection = TRUE;
463 session_bus_stop ();
464 while (data.num_lost != 2)
465 g_main_loop_run (loop);
466 g_assert_cmpint (data.num_acquired, ==, 2);
467 g_assert_cmpint (data.num_lost, ==, 2);
468 g_bus_unown_name (id);
469 g_assert_cmpint (data.num_free_func, ==, 5);
470
471 g_object_unref (c);
472 g_object_unref (c2);
473
474 session_bus_down ();
475 }
476
477 /* ---------------------------------------------------------------------------------------------------- */
478 /* Test that g_bus_watch_name() works correctly */
479 /* ---------------------------------------------------------------------------------------------------- */
480
481 typedef struct
482 {
483 gboolean expect_null_connection;
484 guint num_acquired;
485 guint num_lost;
486 guint num_appeared;
487 guint num_vanished;
488 guint num_free_func;
489 } WatchNameData;
490
491 static void
watch_name_data_free_func(WatchNameData * data)492 watch_name_data_free_func (WatchNameData *data)
493 {
494 data->num_free_func++;
495 g_main_loop_quit (loop);
496 }
497
498 static void
w_bus_acquired_handler(GDBusConnection * connection,const gchar * name,gpointer user_data)499 w_bus_acquired_handler (GDBusConnection *connection,
500 const gchar *name,
501 gpointer user_data)
502 {
503 }
504
505 static void
w_name_acquired_handler(GDBusConnection * connection,const gchar * name,gpointer user_data)506 w_name_acquired_handler (GDBusConnection *connection,
507 const gchar *name,
508 gpointer user_data)
509 {
510 WatchNameData *data = user_data;
511 data->num_acquired += 1;
512 g_main_loop_quit (loop);
513 }
514
515 static void
w_name_lost_handler(GDBusConnection * connection,const gchar * name,gpointer user_data)516 w_name_lost_handler (GDBusConnection *connection,
517 const gchar *name,
518 gpointer user_data)
519 {
520 WatchNameData *data = user_data;
521 data->num_lost += 1;
522 g_main_loop_quit (loop);
523 }
524
525 static void
name_appeared_handler(GDBusConnection * connection,const gchar * name,const gchar * name_owner,gpointer user_data)526 name_appeared_handler (GDBusConnection *connection,
527 const gchar *name,
528 const gchar *name_owner,
529 gpointer user_data)
530 {
531 WatchNameData *data = user_data;
532 if (data->expect_null_connection)
533 {
534 g_assert (connection == NULL);
535 }
536 else
537 {
538 g_assert (connection != NULL);
539 g_dbus_connection_set_exit_on_close (connection, FALSE);
540 }
541 data->num_appeared += 1;
542 g_main_loop_quit (loop);
543 }
544
545 static void
name_vanished_handler(GDBusConnection * connection,const gchar * name,gpointer user_data)546 name_vanished_handler (GDBusConnection *connection,
547 const gchar *name,
548 gpointer user_data)
549 {
550 WatchNameData *data = user_data;
551 if (data->expect_null_connection)
552 {
553 g_assert (connection == NULL);
554 }
555 else
556 {
557 g_assert (connection != NULL);
558 g_dbus_connection_set_exit_on_close (connection, FALSE);
559 }
560 data->num_vanished += 1;
561 g_main_loop_quit (loop);
562 }
563
564 static void
test_bus_watch_name(void)565 test_bus_watch_name (void)
566 {
567 WatchNameData data;
568 guint id;
569 guint owner_id;
570 GDBusConnection *connection;
571
572 /*
573 * First check that name_vanished_handler() is invoked if there is no bus.
574 *
575 * Also make sure name_vanished_handler() isn't invoked when unwatching the name.
576 */
577 data.num_free_func = 0;
578 data.num_appeared = 0;
579 data.num_vanished = 0;
580 data.expect_null_connection = TRUE;
581 id = g_bus_watch_name (G_BUS_TYPE_SESSION,
582 "org.gtk.GDBus.Name1",
583 G_BUS_NAME_WATCHER_FLAGS_NONE,
584 name_appeared_handler,
585 name_vanished_handler,
586 &data,
587 (GDestroyNotify) watch_name_data_free_func);
588 g_assert_cmpint (data.num_appeared, ==, 0);
589 g_assert_cmpint (data.num_vanished, ==, 0);
590 g_main_loop_run (loop);
591 g_assert_cmpint (data.num_appeared, ==, 0);
592 g_assert_cmpint (data.num_vanished, ==, 1);
593 g_bus_unwatch_name (id);
594 g_assert_cmpint (data.num_appeared, ==, 0);
595 g_assert_cmpint (data.num_vanished, ==, 1);
596 g_assert_cmpint (data.num_free_func, ==, 1);
597
598 /*
599 * Now bring up a bus, own a name, and then start watching it.
600 */
601 session_bus_up ();
602 /* own the name */
603 data.num_free_func = 0;
604 data.num_acquired = 0;
605 data.num_lost = 0;
606 data.expect_null_connection = FALSE;
607 owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
608 "org.gtk.GDBus.Name1",
609 G_BUS_NAME_OWNER_FLAGS_NONE,
610 w_bus_acquired_handler,
611 w_name_acquired_handler,
612 w_name_lost_handler,
613 &data,
614 (GDestroyNotify) watch_name_data_free_func);
615 g_main_loop_run (loop);
616 g_assert_cmpint (data.num_acquired, ==, 1);
617 g_assert_cmpint (data.num_lost, ==, 0);
618
619 connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
620 g_assert (connection != NULL);
621
622 /* now watch the name */
623 data.num_appeared = 0;
624 data.num_vanished = 0;
625 id = g_bus_watch_name_on_connection (connection,
626 "org.gtk.GDBus.Name1",
627 G_BUS_NAME_WATCHER_FLAGS_NONE,
628 name_appeared_handler,
629 name_vanished_handler,
630 &data,
631 (GDestroyNotify) watch_name_data_free_func);
632 g_assert_cmpint (data.num_appeared, ==, 0);
633 g_assert_cmpint (data.num_vanished, ==, 0);
634 g_main_loop_run (loop);
635 g_assert_cmpint (data.num_appeared, ==, 1);
636 g_assert_cmpint (data.num_vanished, ==, 0);
637
638 /*
639 * Unwatch the name.
640 */
641 g_bus_unwatch_name (id);
642 g_assert_cmpint (data.num_free_func, ==, 1);
643
644 g_object_unref (connection);
645
646 /* unown the name */
647 g_bus_unown_name (owner_id);
648 g_assert_cmpint (data.num_acquired, ==, 1);
649 g_assert_cmpint (data.num_free_func, ==, 2);
650
651 /*
652 * Create a watcher and then make a name be owned.
653 *
654 * This should trigger name_appeared_handler() ...
655 */
656 /* watch the name */
657 data.num_appeared = 0;
658 data.num_vanished = 0;
659 data.num_free_func = 0;
660 id = g_bus_watch_name_with_closures (G_BUS_TYPE_SESSION,
661 "org.gtk.GDBus.Name1",
662 G_BUS_NAME_WATCHER_FLAGS_NONE,
663 g_cclosure_new (G_CALLBACK (name_appeared_handler),
664 &data,
665 NULL),
666 g_cclosure_new (G_CALLBACK (name_vanished_handler),
667 &data,
668 (GClosureNotify) watch_name_data_free_func));
669 g_assert_cmpint (data.num_appeared, ==, 0);
670 g_assert_cmpint (data.num_vanished, ==, 0);
671 g_main_loop_run (loop);
672 g_assert_cmpint (data.num_appeared, ==, 0);
673 g_assert_cmpint (data.num_vanished, ==, 1);
674
675 /* own the name */
676 data.num_acquired = 0;
677 data.num_lost = 0;
678 data.expect_null_connection = FALSE;
679 owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
680 "org.gtk.GDBus.Name1",
681 G_BUS_NAME_OWNER_FLAGS_NONE,
682 w_bus_acquired_handler,
683 w_name_acquired_handler,
684 w_name_lost_handler,
685 &data,
686 (GDestroyNotify) watch_name_data_free_func);
687 while (data.num_acquired == 0 || data.num_appeared == 0)
688 g_main_loop_run (loop);
689 g_assert_cmpint (data.num_acquired, ==, 1);
690 g_assert_cmpint (data.num_lost, ==, 0);
691 g_assert_cmpint (data.num_appeared, ==, 1);
692 g_assert_cmpint (data.num_vanished, ==, 1);
693
694 /*
695 * Nuke the bus and check that the name vanishes and is lost.
696 */
697 data.expect_null_connection = TRUE;
698 session_bus_stop ();
699 g_main_loop_run (loop);
700 g_assert_cmpint (data.num_lost, ==, 1);
701 g_assert_cmpint (data.num_vanished, ==, 2);
702
703 g_bus_unwatch_name (id);
704 g_assert_cmpint (data.num_free_func, ==, 1);
705
706 g_bus_unown_name (owner_id);
707 g_assert_cmpint (data.num_free_func, ==, 2);
708
709 session_bus_down ();
710 }
711
712 /* ---------------------------------------------------------------------------------------------------- */
713
714 static void
test_validate_names(void)715 test_validate_names (void)
716 {
717 guint n;
718 static const struct
719 {
720 gboolean name;
721 gboolean unique;
722 gboolean interface;
723 const gchar *string;
724 } names[] = {
725 { 1, 0, 1, "valid.well_known.name"},
726 { 1, 0, 0, "valid.well-known.name"},
727 { 1, 1, 0, ":valid.unique.name"},
728 { 0, 0, 0, "invalid.5well_known.name"},
729 { 0, 0, 0, "4invalid.5well_known.name"},
730 { 1, 1, 0, ":4valid.5unique.name"},
731 { 0, 0, 0, ""},
732 { 1, 0, 1, "very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.name1"}, /* 255 */
733 { 0, 0, 0, "very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.very.long.name12"}, /* 256 - too long! */
734 { 0, 0, 0, ".starts.with.a.dot"},
735 { 0, 0, 0, "contains.invalid;.characters"},
736 { 0, 0, 0, "contains.inva/lid.characters"},
737 { 0, 0, 0, "contains.inva[lid.characters"},
738 { 0, 0, 0, "contains.inva]lid.characters"},
739 { 0, 0, 0, "contains.inva_æøå_lid.characters"},
740 { 1, 1, 0, ":1.1"},
741 };
742
743 for (n = 0; n < G_N_ELEMENTS (names); n++)
744 {
745 if (names[n].name)
746 g_assert (g_dbus_is_name (names[n].string));
747 else
748 g_assert (!g_dbus_is_name (names[n].string));
749
750 if (names[n].unique)
751 g_assert (g_dbus_is_unique_name (names[n].string));
752 else
753 g_assert (!g_dbus_is_unique_name (names[n].string));
754
755 if (names[n].interface)
756 g_assert (g_dbus_is_interface_name (names[n].string));
757 else
758 g_assert (!g_dbus_is_interface_name (names[n].string));
759 }
760 }
761
762 /* ---------------------------------------------------------------------------------------------------- */
763
764 int
main(int argc,char * argv[])765 main (int argc,
766 char *argv[])
767 {
768 gint ret;
769
770 g_test_init (&argc, &argv, NULL);
771
772 loop = g_main_loop_new (NULL, FALSE);
773
774 g_test_dbus_unset ();
775
776 g_test_add_func ("/gdbus/validate-names", test_validate_names);
777 g_test_add_func ("/gdbus/bus-own-name", test_bus_own_name);
778 g_test_add_func ("/gdbus/bus-watch-name", test_bus_watch_name);
779
780 ret = g_test_run();
781
782 g_main_loop_unref (loop);
783
784 return ret;
785 }
786