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