GDBus: fix name test cases
[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_with_closures (G_BUS_TYPE_SESSION,
224                                      name,
225                                      G_BUS_NAME_OWNER_FLAGS_NONE,
226                                      g_cclosure_new (G_CALLBACK (bus_acquired_handler),
227                                                      &data,
228                                                      NULL),
229                                      g_cclosure_new (G_CALLBACK (name_acquired_handler),
230                                                      &data,
231                                                      NULL),
232                                      g_cclosure_new (G_CALLBACK (name_lost_handler),
233                                                      &data,
234                                                      (GClosureNotify) own_name_data_free_func));
235   g_assert_cmpint (data.num_bus_acquired, ==, 0);
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, ==, 0);
241   g_assert_cmpint (data.num_lost,     ==, 0);
242   g_main_loop_run (loop);
243   g_assert_cmpint (data.num_bus_acquired, ==, 1);
244   g_assert_cmpint (data.num_acquired, ==, 1);
245   g_assert_cmpint (data.num_lost,     ==, 0);
246
247   /*
248    * Try owning the name with another object on the same connection  - this should
249    * fail because we already own the name.
250    */
251   data2.num_free_func = 0;
252   data2.num_bus_acquired = 0;
253   data2.num_acquired = 0;
254   data2.num_lost = 0;
255   data2.expect_null_connection = FALSE;
256   id2 = g_bus_own_name (G_BUS_TYPE_SESSION,
257                         name,
258                         G_BUS_NAME_OWNER_FLAGS_NONE,
259                         bus_acquired_handler,
260                         name_acquired_handler,
261                         name_lost_handler,
262                         &data2,
263                         (GDestroyNotify) own_name_data_free_func);
264   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
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,     ==, 0);
271   g_main_loop_run (loop);
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_bus_unown_name (id2);
276   g_assert_cmpint (data2.num_bus_acquired, ==, 1);
277   g_assert_cmpint (data2.num_acquired, ==, 0);
278   g_assert_cmpint (data2.num_lost,     ==, 1);
279   g_assert_cmpint (data2.num_free_func, ==, 1);
280
281   /*
282    * Create a secondary (e.g. private) connection and try owning the name on that
283    * connection. This should fail both with and without _REPLACE because we
284    * didn't specify ALLOW_REPLACEMENT.
285    */
286   c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
287   g_assert (c2 != NULL);
288   g_assert (!g_dbus_connection_is_closed (c2));
289   /* first without _REPLACE */
290   data2.num_bus_acquired = 0;
291   data2.num_acquired = 0;
292   data2.num_lost = 0;
293   data2.expect_null_connection = FALSE;
294   data2.num_free_func = 0;
295   id2 = g_bus_own_name_on_connection (c2,
296                                       name,
297                                       G_BUS_NAME_OWNER_FLAGS_NONE,
298                                       name_acquired_handler,
299                                       name_lost_handler,
300                                       &data2,
301                                       (GDestroyNotify) own_name_data_free_func);
302   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
303   g_assert_cmpint (data2.num_acquired, ==, 0);
304   g_assert_cmpint (data2.num_lost,     ==, 0);
305   g_main_loop_run (loop);
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_bus_unown_name (id2);
310   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
311   g_assert_cmpint (data2.num_acquired, ==, 0);
312   g_assert_cmpint (data2.num_lost,     ==, 1);
313   g_assert_cmpint (data2.num_free_func, ==, 1);
314   /* then with _REPLACE */
315   data2.num_bus_acquired = 0;
316   data2.num_acquired = 0;
317   data2.num_lost = 0;
318   data2.expect_null_connection = FALSE;
319   data2.num_free_func = 0;
320   id2 = g_bus_own_name_on_connection (c2,
321                                       name,
322                                       G_BUS_NAME_OWNER_FLAGS_REPLACE,
323                                       name_acquired_handler,
324                                       name_lost_handler,
325                                       &data2,
326                                       (GDestroyNotify) own_name_data_free_func);
327   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
328   g_assert_cmpint (data2.num_acquired, ==, 0);
329   g_assert_cmpint (data2.num_lost,     ==, 0);
330   g_main_loop_run (loop);
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_bus_unown_name (id2);
335   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
336   g_assert_cmpint (data2.num_acquired, ==, 0);
337   g_assert_cmpint (data2.num_lost,     ==, 1);
338   g_assert_cmpint (data2.num_free_func, ==, 1);
339
340   /*
341    * Stop owning the name and grab it again with _ALLOW_REPLACEMENT.
342    */
343   data.expect_null_connection = FALSE;
344   g_bus_unown_name (id);
345   g_assert_cmpint (data.num_bus_acquired, ==, 1);
346   g_assert_cmpint (data.num_acquired, ==, 1);
347   g_assert_cmpint (data.num_free_func, ==, 3);
348   /* grab it again */
349   data.num_bus_acquired = 0;
350   data.num_acquired = 0;
351   data.num_lost = 0;
352   data.expect_null_connection = FALSE;
353   id = g_bus_own_name (G_BUS_TYPE_SESSION,
354                        name,
355                        G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
356                        bus_acquired_handler,
357                        name_acquired_handler,
358                        name_lost_handler,
359                        &data,
360                        (GDestroyNotify) own_name_data_free_func);
361   g_assert_cmpint (data.num_bus_acquired, ==, 0);
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, ==, 0);
367   g_assert_cmpint (data.num_lost,     ==, 0);
368   g_main_loop_run (loop);
369   g_assert_cmpint (data.num_bus_acquired, ==, 1);
370   g_assert_cmpint (data.num_acquired, ==, 1);
371   g_assert_cmpint (data.num_lost,     ==, 0);
372
373   /*
374    * Now try to grab the name from the secondary connection.
375    *
376    */
377   /* first without _REPLACE - this won't make us acquire the name */
378   data2.num_bus_acquired = 0;
379   data2.num_acquired = 0;
380   data2.num_lost = 0;
381   data2.expect_null_connection = FALSE;
382   data2.num_free_func = 0;
383   id2 = g_bus_own_name_on_connection (c2,
384                                       name,
385                                       G_BUS_NAME_OWNER_FLAGS_NONE,
386                                       name_acquired_handler,
387                                       name_lost_handler,
388                                       &data2,
389                                       (GDestroyNotify) own_name_data_free_func);
390   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
391   g_assert_cmpint (data2.num_acquired, ==, 0);
392   g_assert_cmpint (data2.num_lost,     ==, 0);
393   g_main_loop_run (loop);
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_bus_unown_name (id2);
398   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
399   g_assert_cmpint (data2.num_acquired, ==, 0);
400   g_assert_cmpint (data2.num_lost,     ==, 1);
401   g_assert_cmpint (data2.num_free_func, ==, 1);
402   /* then with _REPLACE - here we should acquire the name - e.g. owner should lose it
403    * and owner2 should acquire it  */
404   data2.num_bus_acquired = 0;
405   data2.num_acquired = 0;
406   data2.num_lost = 0;
407   data2.expect_null_connection = FALSE;
408   data2.num_free_func = 0;
409   id2 = g_bus_own_name_on_connection (c2,
410                                       name,
411                                       G_BUS_NAME_OWNER_FLAGS_REPLACE,
412                                       name_acquired_handler,
413                                       name_lost_handler,
414                                       &data2,
415                                       (GDestroyNotify) own_name_data_free_func);
416   g_assert_cmpint (data.num_acquired, ==, 1);
417   g_assert_cmpint (data.num_lost,     ==, 0);
418   g_assert_cmpint (data2.num_acquired, ==, 0);
419   g_assert_cmpint (data2.num_lost,     ==, 0);
420   /* wait for handlers for both owner and owner2 to fire */
421   while (data.num_lost == 0 || data2.num_acquired == 0)
422     g_main_loop_run (loop);
423   g_assert_cmpint (data.num_acquired, ==, 1);
424   g_assert_cmpint (data.num_lost,     ==, 1);
425   g_assert_cmpint (data2.num_acquired, ==, 1);
426   g_assert_cmpint (data2.num_lost,     ==, 0);
427   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
428   /* ok, make owner2 release the name - then wait for owner to automagically reacquire it */
429   g_bus_unown_name (id2);
430   g_assert_cmpint (data2.num_free_func, ==, 1);
431   g_main_loop_run (loop);
432   g_assert_cmpint (data.num_acquired, ==, 2);
433   g_assert_cmpint (data.num_lost,     ==, 1);
434
435   /*
436    * Finally, nuke the bus and check name_lost_handler() is invoked.
437    *
438    */
439   data.expect_null_connection = TRUE;
440   session_bus_down ();
441   while (data.num_lost != 2)
442     g_main_loop_run (loop);
443   g_assert_cmpint (data.num_acquired, ==, 2);
444   g_assert_cmpint (data.num_lost,     ==, 2);
445   g_bus_unown_name (id);
446   g_assert_cmpint (data.num_free_func, ==, 4);
447
448   _g_object_wait_for_single_ref (c);
449   g_object_unref (c);
450   g_object_unref (c2);
451 }
452
453 /* ---------------------------------------------------------------------------------------------------- */
454 /* Test that g_bus_watch_name() works correctly */
455 /* ---------------------------------------------------------------------------------------------------- */
456
457 typedef struct
458 {
459   gboolean expect_null_connection;
460   guint num_acquired;
461   guint num_lost;
462   guint num_appeared;
463   guint num_vanished;
464   guint num_free_func;
465 } WatchNameData;
466
467 static void
468 watch_name_data_free_func (WatchNameData *data)
469 {
470   data->num_free_func++;
471   g_main_loop_quit (loop);
472 }
473
474 static void
475 w_bus_acquired_handler (GDBusConnection *connection,
476                         const gchar     *name,
477                         gpointer         user_data)
478 {
479 }
480
481 static void
482 w_name_acquired_handler (GDBusConnection *connection,
483                          const gchar     *name,
484                          gpointer         user_data)
485 {
486   WatchNameData *data = user_data;
487   data->num_acquired += 1;
488   g_main_loop_quit (loop);
489 }
490
491 static void
492 w_name_lost_handler (GDBusConnection *connection,
493                      const gchar     *name,
494                      gpointer         user_data)
495 {
496   WatchNameData *data = user_data;
497   data->num_lost += 1;
498   g_main_loop_quit (loop);
499 }
500
501 static void
502 name_appeared_handler (GDBusConnection *connection,
503                        const gchar     *name,
504                        const gchar     *name_owner,
505                        gpointer         user_data)
506 {
507   WatchNameData *data = user_data;
508   if (data->expect_null_connection)
509     {
510       g_assert (connection == NULL);
511     }
512   else
513     {
514       g_assert (connection != NULL);
515       g_dbus_connection_set_exit_on_close (connection, FALSE);
516     }
517   data->num_appeared += 1;
518   g_main_loop_quit (loop);
519 }
520
521 static void
522 name_vanished_handler (GDBusConnection *connection,
523                        const gchar     *name,
524                        gpointer         user_data)
525 {
526   WatchNameData *data = user_data;
527   if (data->expect_null_connection)
528     {
529       g_assert (connection == NULL);
530     }
531   else
532     {
533       g_assert (connection != NULL);
534       g_dbus_connection_set_exit_on_close (connection, FALSE);
535     }
536   data->num_vanished += 1;
537   g_main_loop_quit (loop);
538 }
539
540 static void
541 test_bus_watch_name (void)
542 {
543   WatchNameData data;
544   guint id;
545   guint owner_id;
546   GDBusConnection *connection;
547
548   /*
549    * First check that name_vanished_handler() is invoked if there is no bus.
550    *
551    * Also make sure name_vanished_handler() isn't invoked when unwatching the name.
552    */
553   data.num_free_func = 0;
554   data.num_appeared = 0;
555   data.num_vanished = 0;
556   data.expect_null_connection = TRUE;
557   id = g_bus_watch_name (G_BUS_TYPE_SESSION,
558                          "org.gtk.GDBus.Name1",
559                          G_BUS_NAME_WATCHER_FLAGS_NONE,
560                          name_appeared_handler,
561                          name_vanished_handler,
562                          &data,
563                          (GDestroyNotify) watch_name_data_free_func);
564   g_assert_cmpint (data.num_appeared, ==, 0);
565   g_assert_cmpint (data.num_vanished, ==, 0);
566   g_main_loop_run (loop);
567   g_assert_cmpint (data.num_appeared, ==, 0);
568   g_assert_cmpint (data.num_vanished, ==, 1);
569   g_bus_unwatch_name (id);
570   g_assert_cmpint (data.num_appeared, ==, 0);
571   g_assert_cmpint (data.num_vanished, ==, 1);
572   g_assert_cmpint (data.num_free_func, ==, 1);
573
574   /*
575    * Now bring up a bus, own a name, and then start watching it.
576    */
577   session_bus_up ();
578   /* own the name */
579   data.num_free_func = 0;
580   data.num_acquired = 0;
581   data.num_lost = 0;
582   data.expect_null_connection = FALSE;
583   owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
584                              "org.gtk.GDBus.Name1",
585                              G_BUS_NAME_OWNER_FLAGS_NONE,
586                              w_bus_acquired_handler,
587                              w_name_acquired_handler,
588                              w_name_lost_handler,
589                              &data,
590                              (GDestroyNotify) watch_name_data_free_func);
591   g_main_loop_run (loop);
592   g_assert_cmpint (data.num_acquired, ==, 1);
593   g_assert_cmpint (data.num_lost,     ==, 0);
594
595   connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
596   g_assert (connection != NULL);
597
598   /* now watch the name */
599   data.num_appeared = 0;
600   data.num_vanished = 0;
601   id = g_bus_watch_name_on_connection (connection,
602                                        "org.gtk.GDBus.Name1",
603                                        G_BUS_NAME_WATCHER_FLAGS_NONE,
604                                        name_appeared_handler,
605                                        name_vanished_handler,
606                                        &data,
607                                        (GDestroyNotify) watch_name_data_free_func);
608   g_assert_cmpint (data.num_appeared, ==, 0);
609   g_assert_cmpint (data.num_vanished, ==, 0);
610   g_main_loop_run (loop);
611   g_assert_cmpint (data.num_appeared, ==, 1);
612   g_assert_cmpint (data.num_vanished, ==, 0);
613
614   /*
615    * Unwatch the name.
616    */
617   g_bus_unwatch_name (id);
618   g_assert_cmpint (data.num_free_func, ==, 1);
619
620   g_object_unref (connection);
621
622   /* unown the name */
623   g_bus_unown_name (owner_id);
624   g_assert_cmpint (data.num_acquired, ==, 1);
625   g_assert_cmpint (data.num_free_func, ==, 2);
626
627   /*
628    * Create a watcher and then make a name be owned.
629    *
630    * This should trigger name_appeared_handler() ...
631    */
632   /* watch the name */
633   data.num_appeared = 0;
634   data.num_vanished = 0;
635   data.num_free_func = 0;
636   id = g_bus_watch_name_with_closures (G_BUS_TYPE_SESSION,
637                                        "org.gtk.GDBus.Name1",
638                                        G_BUS_NAME_WATCHER_FLAGS_NONE,
639                                        g_cclosure_new (G_CALLBACK (name_appeared_handler),
640                                                        &data,
641                                                        NULL),
642                                        g_cclosure_new (G_CALLBACK (name_vanished_handler),
643                                                        &data,
644                                                        (GClosureNotify) watch_name_data_free_func));
645   g_assert_cmpint (data.num_appeared, ==, 0);
646   g_assert_cmpint (data.num_vanished, ==, 0);
647   g_main_loop_run (loop);
648   g_assert_cmpint (data.num_appeared, ==, 0);
649   g_assert_cmpint (data.num_vanished, ==, 1);
650
651   /* own the name */
652   data.num_acquired = 0;
653   data.num_lost = 0;
654   data.expect_null_connection = FALSE;
655   owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
656                              "org.gtk.GDBus.Name1",
657                              G_BUS_NAME_OWNER_FLAGS_NONE,
658                              w_bus_acquired_handler,
659                              w_name_acquired_handler,
660                              w_name_lost_handler,
661                              &data,
662                              (GDestroyNotify) watch_name_data_free_func);
663   while (data.num_acquired == 0 || data.num_appeared == 0)
664     g_main_loop_run (loop);
665   g_assert_cmpint (data.num_acquired, ==, 1);
666   g_assert_cmpint (data.num_lost,     ==, 0);
667   g_assert_cmpint (data.num_appeared, ==, 1);
668   g_assert_cmpint (data.num_vanished, ==, 1);
669
670   /*
671    * Nuke the bus and check that the name vanishes and is lost.
672    */
673   data.expect_null_connection = TRUE;
674   session_bus_down ();
675   g_main_loop_run (loop);
676   g_assert_cmpint (data.num_lost,     ==, 1);
677   g_assert_cmpint (data.num_vanished, ==, 2);
678
679   g_bus_unwatch_name (id);
680   g_assert_cmpint (data.num_free_func, ==, 1);
681
682   g_bus_unown_name (owner_id);
683   g_assert_cmpint (data.num_free_func, ==, 2);
684
685 }
686
687 /* ---------------------------------------------------------------------------------------------------- */
688
689 static void
690 test_validate_names (void)
691 {
692   guint n;
693   static const struct
694   {
695     gboolean name;
696     gboolean unique;
697     gboolean interface;
698     const gchar *string;
699   } names[] = {
700     { 1, 0, 1, "valid.well_known.name"},
701     { 1, 0, 0, "valid.well-known.name"},
702     { 1, 1, 0, ":valid.unique.name"},
703     { 0, 0, 0, "invalid.5well_known.name"},
704     { 0, 0, 0, "4invalid.5well_known.name"},
705     { 1, 1, 0, ":4valid.5unique.name"},
706     { 0, 0, 0, ""},
707     { 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 */
708     { 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! */
709     { 0, 0, 0, ".starts.with.a.dot"},
710     { 0, 0, 0, "contains.invalid;.characters"},
711     { 0, 0, 0, "contains.inva/lid.characters"},
712     { 0, 0, 0, "contains.inva[lid.characters"},
713     { 0, 0, 0, "contains.inva]lid.characters"},
714     { 0, 0, 0, "contains.inva_æøå_lid.characters"},
715     { 1, 1, 0, ":1.1"},
716   };
717
718   for (n = 0; n < G_N_ELEMENTS (names); n++)
719     {
720       if (names[n].name)
721         g_assert (g_dbus_is_name (names[n].string));
722       else
723         g_assert (!g_dbus_is_name (names[n].string));
724
725       if (names[n].unique)
726         g_assert (g_dbus_is_unique_name (names[n].string));
727       else
728         g_assert (!g_dbus_is_unique_name (names[n].string));
729
730       if (names[n].interface)
731         g_assert (g_dbus_is_interface_name (names[n].string));
732       else
733         g_assert (!g_dbus_is_interface_name (names[n].string));
734     }
735 }
736
737 /* ---------------------------------------------------------------------------------------------------- */
738
739 int
740 main (int   argc,
741       char *argv[])
742 {
743   gint ret;
744
745   g_type_init ();
746   g_test_init (&argc, &argv, NULL);
747
748   loop = g_main_loop_new (NULL, FALSE);
749
750   /* all the tests use a session bus with a well-known address that we can bring up and down
751    * using session_bus_up() and session_bus_down().
752    */
753   g_unsetenv ("DISPLAY");
754   g_setenv ("DBUS_SESSION_BUS_ADDRESS", session_bus_get_temporary_address (), TRUE);
755
756   g_test_add_func ("/gdbus/validate-names", test_validate_names);
757   g_test_add_func ("/gdbus/bus-own-name", test_bus_own_name);
758   g_test_add_func ("/gdbus/bus-watch-name", test_bus_watch_name);
759
760   ret = g_test_run();
761
762   g_main_loop_unref (loop);
763
764   return ret;
765 }