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