Updated FSF's address
[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, 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
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
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
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
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
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
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
499 w_bus_acquired_handler (GDBusConnection *connection,
500                         const gchar     *name,
501                         gpointer         user_data)
502 {
503 }
504
505 static void
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
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
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
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
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
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
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 }