LCOV - code coverage report
Current view: top level - gio/tests - gdbus-names.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 99.4 % 640 636
Test Date: 2024-11-26 05:23:01 Functions: 100.0 % 25 25
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* GLib testing framework examples and tests
       2                 :             :  *
       3                 :             :  * Copyright (C) 2008-2010 Red Hat, Inc.
       4                 :             :  * Copyright (C) 2021 Frederic Martinsons
       5                 :             :  *
       6                 :             :  * SPDX-License-Identifier: LGPL-2.1-or-later
       7                 :             :  *
       8                 :             :  * This library is free software; you can redistribute it and/or
       9                 :             :  * modify it under the terms of the GNU Lesser General Public
      10                 :             :  * License as published by the Free Software Foundation; either
      11                 :             :  * version 2.1 of the License, or (at your option) any later version.
      12                 :             :  *
      13                 :             :  * This library is distributed in the hope that it will be useful,
      14                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16                 :             :  * Lesser General Public License for more details.
      17                 :             :  *
      18                 :             :  * You should have received a copy of the GNU Lesser General
      19                 :             :  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      20                 :             :  *
      21                 :             :  * Author: David Zeuthen <davidz@redhat.com>
      22                 :             :  * Author: Frederic Martinsons <frederic.martinsons@gmail.com>
      23                 :             :  */
      24                 :             : 
      25                 :             : #include <gio/gio.h>
      26                 :             : #include <unistd.h>
      27                 :             : 
      28                 :             : #include "gdbusprivate.h"
      29                 :             : #include "gdbus-tests.h"
      30                 :             : 
      31                 :             : /* ---------------------------------------------------------------------------------------------------- */
      32                 :             : /* Test that g_bus_own_name() works correctly */
      33                 :             : /* ---------------------------------------------------------------------------------------------------- */
      34                 :             : 
      35                 :             : typedef struct
      36                 :             : {
      37                 :             :   gboolean expect_null_connection;
      38                 :             :   guint num_bus_acquired;
      39                 :             :   guint num_acquired;
      40                 :             :   guint num_lost;
      41                 :             :   guint num_free_func;
      42                 :             :   GMainContext *main_context;  /* (unowned) */
      43                 :             : } OwnNameData;
      44                 :             : 
      45                 :             : static void
      46                 :          21 : own_name_data_free_func (OwnNameData *data)
      47                 :             : {
      48                 :          21 :   data->num_free_func++;
      49                 :          21 :   g_main_context_wakeup (data->main_context);
      50                 :          21 : }
      51                 :             : 
      52                 :             : static void
      53                 :           4 : bus_acquired_handler (GDBusConnection *connection,
      54                 :             :                       const gchar     *name,
      55                 :             :                       gpointer         user_data)
      56                 :             : {
      57                 :           4 :   OwnNameData *data = user_data;
      58                 :           4 :   g_dbus_connection_set_exit_on_close (connection, FALSE);
      59                 :           4 :   data->num_bus_acquired += 1;
      60                 :           4 :   g_main_context_wakeup (data->main_context);
      61                 :           4 : }
      62                 :             : 
      63                 :             : static void
      64                 :           5 : name_acquired_handler (GDBusConnection *connection,
      65                 :             :                        const gchar     *name,
      66                 :             :                        gpointer         user_data)
      67                 :             : {
      68                 :           5 :   OwnNameData *data = user_data;
      69                 :           5 :   data->num_acquired += 1;
      70                 :           5 :   g_main_context_wakeup (data->main_context);
      71                 :           5 : }
      72                 :             : 
      73                 :             : static void
      74                 :           7 : name_lost_handler (GDBusConnection *connection,
      75                 :             :                    const gchar     *name,
      76                 :             :                    gpointer         user_data)
      77                 :             : {
      78                 :           7 :   OwnNameData *data = user_data;
      79                 :           7 :   if (data->expect_null_connection)
      80                 :             :     {
      81                 :           2 :       g_assert (connection == NULL);
      82                 :             :     }
      83                 :             :   else
      84                 :             :     {
      85                 :           5 :       g_assert (connection != NULL);
      86                 :           5 :       g_dbus_connection_set_exit_on_close (connection, FALSE);
      87                 :             :     }
      88                 :           7 :   data->num_lost += 1;
      89                 :           7 :   g_main_context_wakeup (data->main_context);
      90                 :           7 : }
      91                 :             : 
      92                 :             : static void
      93                 :           1 : 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                 :           1 :   GMainContext *main_context = NULL;  /* use the global default for now */
     106                 :             : 
     107                 :           1 :   error = NULL;
     108                 :           1 :   name = "org.gtk.GDBus.Name1";
     109                 :             : 
     110                 :             :   /*
     111                 :             :    * First check that name_lost_handler() is invoked if there is no bus.
     112                 :             :    *
     113                 :             :    * Also make sure name_lost_handler() isn't invoked when unowning the name.
     114                 :             :    */
     115                 :           1 :   data.num_bus_acquired = 0;
     116                 :           1 :   data.num_free_func = 0;
     117                 :           1 :   data.num_acquired = 0;
     118                 :           1 :   data.num_lost = 0;
     119                 :           1 :   data.expect_null_connection = TRUE;
     120                 :           1 :   data.main_context = main_context;
     121                 :           1 :   id = g_bus_own_name (G_BUS_TYPE_SESSION,
     122                 :             :                        name,
     123                 :             :                        G_BUS_NAME_OWNER_FLAGS_NONE,
     124                 :             :                        bus_acquired_handler,
     125                 :             :                        name_acquired_handler,
     126                 :             :                        name_lost_handler,
     127                 :             :                        &data,
     128                 :             :                        (GDestroyNotify) own_name_data_free_func);
     129                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 0);
     130                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 0);
     131                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     132                 :             : 
     133                 :           2 :   while (data.num_lost < 1)
     134                 :           1 :     g_main_context_iteration (main_context, TRUE);
     135                 :             : 
     136                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 0);
     137                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 0);
     138                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 1);
     139                 :           1 :   g_bus_unown_name (id);
     140                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 0);
     141                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 1);
     142                 :           1 :   g_assert_cmpint (data.num_free_func, ==, 1);
     143                 :             : 
     144                 :             :   /*
     145                 :             :    * Bring up a bus, then own a name and check bus_acquired_handler() then name_acquired_handler() is invoked.
     146                 :             :    */
     147                 :           1 :   session_bus_up ();
     148                 :           1 :   data.num_bus_acquired = 0;
     149                 :           1 :   data.num_acquired = 0;
     150                 :           1 :   data.num_lost = 0;
     151                 :           1 :   data.expect_null_connection = FALSE;
     152                 :           1 :   id = g_bus_own_name (G_BUS_TYPE_SESSION,
     153                 :             :                        name,
     154                 :             :                        G_BUS_NAME_OWNER_FLAGS_NONE,
     155                 :             :                        bus_acquired_handler,
     156                 :             :                        name_acquired_handler,
     157                 :             :                        name_lost_handler,
     158                 :             :                        &data,
     159                 :             :                        (GDestroyNotify) own_name_data_free_func);
     160                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 0);
     161                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 0);
     162                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     163                 :             : 
     164                 :           3 :   while (data.num_bus_acquired < 1)
     165                 :           2 :     g_main_context_iteration (main_context, TRUE);
     166                 :             : 
     167                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 1);
     168                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 0);
     169                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     170                 :             : 
     171                 :           3 :   while (data.num_acquired < 1)
     172                 :           2 :     g_main_context_iteration (main_context, TRUE);
     173                 :             : 
     174                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 1);
     175                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 1);
     176                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     177                 :             : 
     178                 :             :   /*
     179                 :             :    * Check that the name was actually acquired.
     180                 :             :    */
     181                 :           1 :   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
     182                 :           1 :   g_assert (c != NULL);
     183                 :           1 :   g_assert (!g_dbus_connection_is_closed (c));
     184                 :           1 :   result = g_dbus_connection_call_sync (c,
     185                 :             :                                         DBUS_SERVICE_DBUS,
     186                 :             :                                         DBUS_PATH_DBUS,
     187                 :             :                                         DBUS_INTERFACE_DBUS,
     188                 :             :                                         "NameHasOwner",          /* method name */
     189                 :             :                                         g_variant_new ("(s)", name),
     190                 :             :                                         G_VARIANT_TYPE ("(b)"),
     191                 :             :                                         G_DBUS_CALL_FLAGS_NONE,
     192                 :             :                                         -1,
     193                 :             :                                         NULL,
     194                 :             :                                         &error);
     195                 :           1 :   g_assert_no_error (error);
     196                 :           1 :   g_assert (result != NULL);
     197                 :           1 :   g_variant_get (result, "(b)", &name_has_owner_reply);
     198                 :           1 :   g_assert (name_has_owner_reply);
     199                 :           1 :   g_variant_unref (result);
     200                 :             : 
     201                 :             :   /*
     202                 :             :    * Stop owning the name - this should invoke our free func
     203                 :             :    */
     204                 :           1 :   g_bus_unown_name (id);
     205                 :           3 :   while (data.num_free_func < 2)
     206                 :           2 :     g_main_context_iteration (main_context, TRUE);
     207                 :           1 :   g_assert_cmpint (data.num_free_func, ==, 2);
     208                 :             : 
     209                 :             :   /*
     210                 :             :    * Check that the name was actually released.
     211                 :             :    */
     212                 :           1 :   result = g_dbus_connection_call_sync (c,
     213                 :             :                                         DBUS_SERVICE_DBUS,
     214                 :             :                                         DBUS_PATH_DBUS,
     215                 :             :                                         DBUS_INTERFACE_DBUS,
     216                 :             :                                         "NameHasOwner",          /* method name */
     217                 :             :                                         g_variant_new ("(s)", name),
     218                 :             :                                         G_VARIANT_TYPE ("(b)"),
     219                 :             :                                         G_DBUS_CALL_FLAGS_NONE,
     220                 :             :                                         -1,
     221                 :             :                                         NULL,
     222                 :             :                                         &error);
     223                 :           1 :   g_assert_no_error (error);
     224                 :           1 :   g_assert (result != NULL);
     225                 :           1 :   g_variant_get (result, "(b)", &name_has_owner_reply);
     226                 :           1 :   g_assert (!name_has_owner_reply);
     227                 :           1 :   g_variant_unref (result);
     228                 :             : 
     229                 :             :   /* Now try owning the name and then immediately decide to unown the name */
     230                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 1);
     231                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 1);
     232                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     233                 :           1 :   g_assert_cmpint (data.num_free_func, ==, 2);
     234                 :           1 :   id = g_bus_own_name (G_BUS_TYPE_SESSION,
     235                 :             :                        name,
     236                 :             :                        G_BUS_NAME_OWNER_FLAGS_NONE,
     237                 :             :                        bus_acquired_handler,
     238                 :             :                        name_acquired_handler,
     239                 :             :                        name_lost_handler,
     240                 :             :                        &data,
     241                 :             :                        (GDestroyNotify) own_name_data_free_func);
     242                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 1);
     243                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 1);
     244                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     245                 :           1 :   g_assert_cmpint (data.num_free_func, ==, 2);
     246                 :           1 :   g_bus_unown_name (id);
     247                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 1);
     248                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 1);
     249                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     250                 :           1 :   g_assert_cmpint (data.num_free_func, ==, 2);
     251                 :             : 
     252                 :             :   /* the GDestroyNotify is called in idle because the bus is acquired in idle */
     253                 :           3 :   while (data.num_free_func < 3)
     254                 :           2 :     g_main_context_iteration (main_context, TRUE);
     255                 :             : 
     256                 :           1 :   g_assert_cmpint (data.num_free_func, ==, 3);
     257                 :             : 
     258                 :             :   /*
     259                 :             :    * Own the name again.
     260                 :             :    */
     261                 :           1 :   data.num_bus_acquired = 0;
     262                 :           1 :   data.num_acquired = 0;
     263                 :           1 :   data.num_lost = 0;
     264                 :           1 :   data.expect_null_connection = FALSE;
     265                 :           1 :   id = g_bus_own_name_with_closures (G_BUS_TYPE_SESSION,
     266                 :             :                                      name,
     267                 :             :                                      G_BUS_NAME_OWNER_FLAGS_NONE,
     268                 :             :                                      g_cclosure_new (G_CALLBACK (bus_acquired_handler),
     269                 :             :                                                      &data,
     270                 :             :                                                      NULL),
     271                 :             :                                      g_cclosure_new (G_CALLBACK (name_acquired_handler),
     272                 :             :                                                      &data,
     273                 :             :                                                      NULL),
     274                 :             :                                      g_cclosure_new (G_CALLBACK (name_lost_handler),
     275                 :             :                                                      &data,
     276                 :             :                                                      (GClosureNotify) own_name_data_free_func));
     277                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 0);
     278                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 0);
     279                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     280                 :             : 
     281                 :           3 :   while (data.num_bus_acquired < 1)
     282                 :           2 :     g_main_context_iteration (main_context, TRUE);
     283                 :             : 
     284                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 1);
     285                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 0);
     286                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     287                 :             : 
     288                 :           3 :   while (data.num_acquired < 1)
     289                 :           2 :     g_main_context_iteration (main_context, TRUE);
     290                 :             : 
     291                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 1);
     292                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 1);
     293                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     294                 :             : 
     295                 :             :   /*
     296                 :             :    * Try owning the name with another object on the same connection  - this should
     297                 :             :    * fail because we already own the name.
     298                 :             :    */
     299                 :           1 :   data2.num_free_func = 0;
     300                 :           1 :   data2.num_bus_acquired = 0;
     301                 :           1 :   data2.num_acquired = 0;
     302                 :           1 :   data2.num_lost = 0;
     303                 :           1 :   data2.expect_null_connection = FALSE;
     304                 :           1 :   data2.main_context = main_context;
     305                 :           1 :   id2 = g_bus_own_name (G_BUS_TYPE_SESSION,
     306                 :             :                         name,
     307                 :             :                         G_BUS_NAME_OWNER_FLAGS_NONE,
     308                 :             :                         bus_acquired_handler,
     309                 :             :                         name_acquired_handler,
     310                 :             :                         name_lost_handler,
     311                 :             :                         &data2,
     312                 :             :                         (GDestroyNotify) own_name_data_free_func);
     313                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
     314                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     315                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 0);
     316                 :             : 
     317                 :           3 :   while (data2.num_bus_acquired < 1)
     318                 :           2 :     g_main_context_iteration (main_context, TRUE);
     319                 :             : 
     320                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 1);
     321                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     322                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 0);
     323                 :             : 
     324                 :           3 :   while (data2.num_lost < 1)
     325                 :           2 :     g_main_context_iteration (main_context, TRUE);
     326                 :             : 
     327                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 1);
     328                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     329                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 1);
     330                 :             : 
     331                 :           1 :   g_bus_unown_name (id2);
     332                 :           2 :   while (data2.num_free_func < 1)
     333                 :           1 :     g_main_context_iteration (main_context, TRUE);
     334                 :             : 
     335                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 1);
     336                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     337                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 1);
     338                 :           1 :   g_assert_cmpint (data2.num_free_func, ==, 1);
     339                 :             : 
     340                 :             :   /*
     341                 :             :    * Create a secondary (e.g. private) connection and try owning the name on that
     342                 :             :    * connection. This should fail both with and without _REPLACE because we
     343                 :             :    * didn't specify ALLOW_REPLACEMENT.
     344                 :             :    */
     345                 :           1 :   c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
     346                 :           1 :   g_assert (c2 != NULL);
     347                 :           1 :   g_assert (!g_dbus_connection_is_closed (c2));
     348                 :             :   /* first without _REPLACE */
     349                 :           1 :   data2.num_bus_acquired = 0;
     350                 :           1 :   data2.num_acquired = 0;
     351                 :           1 :   data2.num_lost = 0;
     352                 :           1 :   data2.expect_null_connection = FALSE;
     353                 :           1 :   data2.num_free_func = 0;
     354                 :           1 :   id2 = g_bus_own_name_on_connection (c2,
     355                 :             :                                       name,
     356                 :             :                                       G_BUS_NAME_OWNER_FLAGS_NONE,
     357                 :             :                                       name_acquired_handler,
     358                 :             :                                       name_lost_handler,
     359                 :             :                                       &data2,
     360                 :             :                                       (GDestroyNotify) own_name_data_free_func);
     361                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
     362                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     363                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 0);
     364                 :             : 
     365                 :           3 :   while (data2.num_lost < 1)
     366                 :           2 :     g_main_context_iteration (main_context, TRUE);
     367                 :             : 
     368                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
     369                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     370                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 1);
     371                 :             : 
     372                 :           1 :   g_bus_unown_name (id2);
     373                 :           2 :   while (data2.num_free_func < 1)
     374                 :           1 :     g_main_context_iteration (main_context, TRUE);
     375                 :             : 
     376                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
     377                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     378                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 1);
     379                 :           1 :   g_assert_cmpint (data2.num_free_func, ==, 1);
     380                 :             :   /* then with _REPLACE */
     381                 :           1 :   data2.num_bus_acquired = 0;
     382                 :           1 :   data2.num_acquired = 0;
     383                 :           1 :   data2.num_lost = 0;
     384                 :           1 :   data2.expect_null_connection = FALSE;
     385                 :           1 :   data2.num_free_func = 0;
     386                 :           1 :   id2 = g_bus_own_name_on_connection (c2,
     387                 :             :                                       name,
     388                 :             :                                       G_BUS_NAME_OWNER_FLAGS_REPLACE,
     389                 :             :                                       name_acquired_handler,
     390                 :             :                                       name_lost_handler,
     391                 :             :                                       &data2,
     392                 :             :                                       (GDestroyNotify) own_name_data_free_func);
     393                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
     394                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     395                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 0);
     396                 :             : 
     397                 :           3 :   while (data2.num_lost < 1)
     398                 :           2 :     g_main_context_iteration (main_context, TRUE);
     399                 :             : 
     400                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
     401                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     402                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 1);
     403                 :             : 
     404                 :           1 :   g_bus_unown_name (id2);
     405                 :           2 :   while (data2.num_free_func < 1)
     406                 :           1 :     g_main_context_iteration (main_context, TRUE);
     407                 :             : 
     408                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
     409                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     410                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 1);
     411                 :           1 :   g_assert_cmpint (data2.num_free_func, ==, 1);
     412                 :             : 
     413                 :             :   /*
     414                 :             :    * Stop owning the name and grab it again with _ALLOW_REPLACEMENT.
     415                 :             :    */
     416                 :           1 :   data.expect_null_connection = FALSE;
     417                 :           1 :   g_bus_unown_name (id);
     418                 :           3 :   while (data.num_bus_acquired < 1 || data.num_free_func < 4)
     419                 :           2 :     g_main_context_iteration (main_context, TRUE);
     420                 :             : 
     421                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 1);
     422                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 1);
     423                 :           1 :   g_assert_cmpint (data.num_free_func, ==, 4);
     424                 :             :   /* grab it again */
     425                 :           1 :   data.num_bus_acquired = 0;
     426                 :           1 :   data.num_acquired = 0;
     427                 :           1 :   data.num_lost = 0;
     428                 :           1 :   data.expect_null_connection = FALSE;
     429                 :           1 :   id = g_bus_own_name (G_BUS_TYPE_SESSION,
     430                 :             :                        name,
     431                 :             :                        G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
     432                 :             :                        bus_acquired_handler,
     433                 :             :                        name_acquired_handler,
     434                 :             :                        name_lost_handler,
     435                 :             :                        &data,
     436                 :             :                        (GDestroyNotify) own_name_data_free_func);
     437                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 0);
     438                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 0);
     439                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     440                 :             : 
     441                 :           3 :   while (data.num_bus_acquired < 1)
     442                 :           2 :     g_main_context_iteration (main_context, TRUE);
     443                 :             : 
     444                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 1);
     445                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 0);
     446                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     447                 :             : 
     448                 :           3 :   while (data.num_acquired < 1)
     449                 :           2 :     g_main_context_iteration (main_context, TRUE);
     450                 :             : 
     451                 :           1 :   g_assert_cmpint (data.num_bus_acquired, ==, 1);
     452                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 1);
     453                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     454                 :             : 
     455                 :             :   /*
     456                 :             :    * Now try to grab the name from the secondary connection.
     457                 :             :    *
     458                 :             :    */
     459                 :             :   /* first without _REPLACE - this won't make us acquire the name */
     460                 :           1 :   data2.num_bus_acquired = 0;
     461                 :           1 :   data2.num_acquired = 0;
     462                 :           1 :   data2.num_lost = 0;
     463                 :           1 :   data2.expect_null_connection = FALSE;
     464                 :           1 :   data2.num_free_func = 0;
     465                 :           1 :   id2 = g_bus_own_name_on_connection (c2,
     466                 :             :                                       name,
     467                 :             :                                       G_BUS_NAME_OWNER_FLAGS_NONE,
     468                 :             :                                       name_acquired_handler,
     469                 :             :                                       name_lost_handler,
     470                 :             :                                       &data2,
     471                 :             :                                       (GDestroyNotify) own_name_data_free_func);
     472                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
     473                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     474                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 0);
     475                 :             : 
     476                 :           3 :   while (data2.num_lost < 1)
     477                 :           2 :     g_main_context_iteration (main_context, TRUE);
     478                 :             : 
     479                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
     480                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     481                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 1);
     482                 :             : 
     483                 :           1 :   g_bus_unown_name (id2);
     484                 :           2 :   while (data2.num_free_func < 1)
     485                 :           1 :     g_main_context_iteration (main_context, TRUE);
     486                 :             : 
     487                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
     488                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     489                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 1);
     490                 :           1 :   g_assert_cmpint (data2.num_free_func, ==, 1);
     491                 :             :   /* then with _REPLACE - here we should acquire the name - e.g. owner should lose it
     492                 :             :    * and owner2 should acquire it  */
     493                 :           1 :   data2.num_bus_acquired = 0;
     494                 :           1 :   data2.num_acquired = 0;
     495                 :           1 :   data2.num_lost = 0;
     496                 :           1 :   data2.expect_null_connection = FALSE;
     497                 :           1 :   data2.num_free_func = 0;
     498                 :           1 :   id2 = g_bus_own_name_on_connection (c2,
     499                 :             :                                       name,
     500                 :             :                                       G_BUS_NAME_OWNER_FLAGS_REPLACE,
     501                 :             :                                       name_acquired_handler,
     502                 :             :                                       name_lost_handler,
     503                 :             :                                       &data2,
     504                 :             :                                       (GDestroyNotify) own_name_data_free_func);
     505                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 1);
     506                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 0);
     507                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 0);
     508                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 0);
     509                 :             : 
     510                 :             :   /* wait for handlers for both owner and owner2 to fire */
     511                 :           3 :   while (data.num_lost == 0 || data2.num_acquired == 0)
     512                 :           2 :     g_main_context_iteration (main_context, TRUE);
     513                 :             : 
     514                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 1);
     515                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 1);
     516                 :           1 :   g_assert_cmpint (data2.num_acquired, ==, 1);
     517                 :           1 :   g_assert_cmpint (data2.num_lost,     ==, 0);
     518                 :           1 :   g_assert_cmpint (data2.num_bus_acquired, ==, 0);
     519                 :             : 
     520                 :             :   /* ok, make owner2 release the name - then wait for owner to automagically reacquire it */
     521                 :           1 :   g_bus_unown_name (id2);
     522                 :           3 :   while (data.num_acquired < 2 || data2.num_free_func < 1)
     523                 :           2 :     g_main_context_iteration (main_context, TRUE);
     524                 :             : 
     525                 :           1 :   g_assert_cmpint (data2.num_free_func, ==, 1);
     526                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 2);
     527                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 1);
     528                 :             : 
     529                 :             :   /*
     530                 :             :    * Finally, nuke the bus and check name_lost_handler() is invoked.
     531                 :             :    *
     532                 :             :    */
     533                 :           1 :   data.expect_null_connection = TRUE;
     534                 :           1 :   session_bus_stop ();
     535                 :           3 :   while (data.num_lost != 2)
     536                 :           2 :     g_main_context_iteration (main_context, TRUE);
     537                 :             : 
     538                 :           1 :   g_assert_cmpint (data.num_acquired, ==, 2);
     539                 :           1 :   g_assert_cmpint (data.num_lost,     ==, 2);
     540                 :             : 
     541                 :           1 :   g_bus_unown_name (id);
     542                 :           2 :   while (data.num_free_func < 5)
     543                 :           1 :     g_main_context_iteration (main_context, TRUE);
     544                 :             : 
     545                 :           1 :   g_assert_cmpint (data.num_free_func, ==, 5);
     546                 :             : 
     547                 :           1 :   g_object_unref (c);
     548                 :           1 :   g_object_unref (c2);
     549                 :             : 
     550                 :           1 :   session_bus_down ();
     551                 :           1 : }
     552                 :             : 
     553                 :             : /* ---------------------------------------------------------------------------------------------------- */
     554                 :             : /* Test that g_bus_watch_name() works correctly */
     555                 :             : /* ---------------------------------------------------------------------------------------------------- */
     556                 :             : 
     557                 :             : typedef struct
     558                 :             : {
     559                 :             :   gboolean expect_null_connection;
     560                 :             :   guint num_acquired;
     561                 :             :   guint num_lost;
     562                 :             :   guint num_appeared;
     563                 :             :   guint num_vanished;
     564                 :             :   guint num_free_func;
     565                 :             :   GMainContext *main_context;  /* (unowned), for the main test thread */
     566                 :             : } WatchNameData;
     567                 :             : 
     568                 :             : typedef struct
     569                 :             : {
     570                 :             :   WatchNameData data;
     571                 :             :   GDBusConnection *connection;
     572                 :             :   GMutex cond_mutex;
     573                 :             :   GCond cond;
     574                 :             :   gboolean started;
     575                 :             :   gboolean name_acquired;
     576                 :             :   gboolean ended;
     577                 :             :   gboolean unwatch_early;
     578                 :             :   GMutex mutex;
     579                 :             :   guint watch_id;
     580                 :             :   GMainContext *thread_context;  /* (unowned), only accessed from watcher_thread() */
     581                 :             : } WatchNameThreadData;
     582                 :             : 
     583                 :             : static void
     584                 :          15 : watch_name_data_free_func (WatchNameData *data)
     585                 :             : {
     586                 :          15 :   data->num_free_func++;
     587                 :          15 :   g_main_context_wakeup (data->main_context);
     588                 :          15 : }
     589                 :             : 
     590                 :             : static void
     591                 :           9 : w_bus_acquired_handler (GDBusConnection *connection,
     592                 :             :                         const gchar     *name,
     593                 :             :                         gpointer         user_data)
     594                 :             : {
     595                 :           9 : }
     596                 :             : 
     597                 :             : static void
     598                 :          11 : w_name_acquired_handler (GDBusConnection *connection,
     599                 :             :                          const gchar     *name,
     600                 :             :                          gpointer         user_data)
     601                 :             : {
     602                 :          11 :   OwnNameData *data = user_data;
     603                 :          11 :   data->num_acquired += 1;
     604                 :          11 :   g_main_context_wakeup (data->main_context);
     605                 :          11 : }
     606                 :             : 
     607                 :             : static void
     608                 :           6 : w_name_lost_handler (GDBusConnection *connection,
     609                 :             :                      const gchar     *name,
     610                 :             :                      gpointer         user_data)
     611                 :             : {
     612                 :           6 :   OwnNameData *data = user_data;
     613                 :           6 :   data->num_lost += 1;
     614                 :           6 :   g_main_context_wakeup (data->main_context);
     615                 :           6 : }
     616                 :             : 
     617                 :             : static void
     618                 :          10 : name_appeared_handler (GDBusConnection *connection,
     619                 :             :                        const gchar     *name,
     620                 :             :                        const gchar     *name_owner,
     621                 :             :                        gpointer         user_data)
     622                 :             : {
     623                 :          10 :   WatchNameData *data = user_data;
     624                 :             : 
     625                 :          10 :   if (data->expect_null_connection)
     626                 :             :     {
     627                 :           0 :       g_assert (connection == NULL);
     628                 :             :     }
     629                 :             :   else
     630                 :             :     {
     631                 :          10 :       g_assert (connection != NULL);
     632                 :          10 :       g_dbus_connection_set_exit_on_close (connection, FALSE);
     633                 :             :     }
     634                 :          10 :   data->num_appeared += 1;
     635                 :          10 :   g_main_context_wakeup (data->main_context);
     636                 :          10 : }
     637                 :             : 
     638                 :             : static void
     639                 :          14 : name_vanished_handler (GDBusConnection *connection,
     640                 :             :                        const gchar     *name,
     641                 :             :                        gpointer         user_data)
     642                 :             : {
     643                 :          14 :   WatchNameData *data = user_data;
     644                 :             : 
     645                 :          14 :   if (data->expect_null_connection)
     646                 :             :     {
     647                 :           9 :       g_assert (connection == NULL);
     648                 :             :     }
     649                 :             :   else
     650                 :             :     {
     651                 :           5 :       g_assert (connection != NULL);
     652                 :           5 :       g_dbus_connection_set_exit_on_close (connection, FALSE);
     653                 :             :     }
     654                 :          14 :   data->num_vanished += 1;
     655                 :          14 :   g_main_context_wakeup (data->main_context);
     656                 :          14 : }
     657                 :             : 
     658                 :             : typedef struct
     659                 :             : {
     660                 :             :   guint watcher_flags;
     661                 :             :   gboolean watch_with_closures;
     662                 :             :   gboolean existing_service;
     663                 :             : } WatchNameTest;
     664                 :             : 
     665                 :             : static const WatchNameTest watch_no_closures_no_flags = {
     666                 :             :   .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_NONE,
     667                 :             :   .watch_with_closures = FALSE,
     668                 :             :   .existing_service = FALSE
     669                 :             : };
     670                 :             : 
     671                 :             : static const WatchNameTest watch_no_closures_flags_auto_start = {
     672                 :             :   .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
     673                 :             :   .watch_with_closures = FALSE,
     674                 :             :   .existing_service = FALSE
     675                 :             : };
     676                 :             : 
     677                 :             : static const WatchNameTest watch_no_closures_flags_auto_start_service_exist = {
     678                 :             :   .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
     679                 :             :   .watch_with_closures = FALSE,
     680                 :             :   .existing_service = TRUE
     681                 :             : };
     682                 :             : 
     683                 :             : static const WatchNameTest watch_closures_no_flags = {
     684                 :             :   .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_NONE,
     685                 :             :   .watch_with_closures = TRUE,
     686                 :             :   .existing_service = FALSE
     687                 :             : };
     688                 :             : 
     689                 :             : static const WatchNameTest watch_closures_flags_auto_start = {
     690                 :             :   .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
     691                 :             :   .watch_with_closures = TRUE,
     692                 :             :   .existing_service = FALSE
     693                 :             : };
     694                 :             : 
     695                 :             : static void
     696                 :           1 : stop_service (GDBusConnection *connection,
     697                 :             :               WatchNameData   *data)
     698                 :             : {
     699                 :           1 :   GError *error = NULL;
     700                 :           1 :   GDBusProxy *proxy = NULL;
     701                 :           1 :   GVariant *result = NULL;
     702                 :           1 :   GMainContext *main_context = NULL;  /* use the global default for now */
     703                 :             : 
     704                 :           1 :   data->num_vanished = 0;
     705                 :             : 
     706                 :           1 :   proxy = g_dbus_proxy_new_sync (connection,
     707                 :             :                                  G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
     708                 :             :                                  NULL,
     709                 :             :                                  "org.gtk.GDBus.FakeService",
     710                 :             :                                  "/org/gtk/GDBus/FakeService",
     711                 :             :                                  "org.gtk.GDBus.FakeService",
     712                 :             :                                  NULL,
     713                 :             :                                  &error);
     714                 :           1 :   g_assert_no_error (error);
     715                 :             : 
     716                 :           1 :   result = g_dbus_proxy_call_sync (proxy,
     717                 :             :                                    "Quit",
     718                 :             :                                    NULL,
     719                 :             :                                    G_DBUS_CALL_FLAGS_NO_AUTO_START,
     720                 :             :                                    100,
     721                 :             :                                    NULL,
     722                 :             :                                    &error);
     723                 :           1 :   g_assert_no_error (error);
     724                 :           1 :   g_object_unref (proxy);
     725                 :           1 :   if (result)
     726                 :           1 :     g_variant_unref (result);
     727                 :           3 :   while (data->num_vanished == 0)
     728                 :           2 :     g_main_context_iteration (main_context, TRUE);
     729                 :           1 : }
     730                 :             : 
     731                 :             : static void
     732                 :           5 : test_bus_watch_name (gconstpointer d)
     733                 :             : {
     734                 :             :   WatchNameData data;
     735                 :             :   OwnNameData own_data;
     736                 :             :   guint id;
     737                 :             :   guint owner_id;
     738                 :             :   GDBusConnection *connection;
     739                 :             :   const WatchNameTest *watch_name_test;
     740                 :             :   const gchar *name;
     741                 :           5 :   GMainContext *main_context = NULL;  /* use the global default for now */
     742                 :             : 
     743                 :           5 :   watch_name_test = (WatchNameTest *) d;
     744                 :             : 
     745                 :           5 :   if (watch_name_test->existing_service)
     746                 :             :     {
     747                 :           1 :       name = "org.gtk.GDBus.FakeService";
     748                 :             :     }
     749                 :             :   else
     750                 :             :     {
     751                 :           4 :       name = "org.gtk.GDBus.Name1";
     752                 :             :     }
     753                 :             : 
     754                 :             :   /*
     755                 :             :    * First check that name_vanished_handler() is invoked if there is no bus.
     756                 :             :    *
     757                 :             :    * Also make sure name_vanished_handler() isn't invoked when unwatching the name.
     758                 :             :    */
     759                 :           5 :   data.num_free_func = 0;
     760                 :           5 :   data.num_appeared = 0;
     761                 :           5 :   data.num_vanished = 0;
     762                 :           5 :   data.expect_null_connection = TRUE;
     763                 :           5 :   data.main_context = main_context;
     764                 :           5 :   id = g_bus_watch_name (G_BUS_TYPE_SESSION,
     765                 :             :                          name,
     766                 :           5 :                          watch_name_test->watcher_flags,
     767                 :             :                          name_appeared_handler,
     768                 :             :                          name_vanished_handler,
     769                 :             :                          &data,
     770                 :             :                          (GDestroyNotify) watch_name_data_free_func);
     771                 :           5 :   g_assert_cmpint (data.num_appeared, ==, 0);
     772                 :           5 :   g_assert_cmpint (data.num_vanished, ==, 0);
     773                 :             : 
     774                 :          10 :   while (data.num_vanished < 1)
     775                 :           5 :     g_main_context_iteration (main_context, TRUE);
     776                 :             : 
     777                 :           5 :   g_assert_cmpint (data.num_appeared, ==, 0);
     778                 :           5 :   g_assert_cmpint (data.num_vanished, ==, 1);
     779                 :             : 
     780                 :           5 :   g_bus_unwatch_name (id);
     781                 :          10 :   while (data.num_free_func < 1)
     782                 :           5 :     g_main_context_iteration (main_context, TRUE);
     783                 :             : 
     784                 :           5 :   g_assert_cmpint (data.num_appeared, ==, 0);
     785                 :           5 :   g_assert_cmpint (data.num_vanished, ==, 1);
     786                 :           5 :   g_assert_cmpint (data.num_free_func, ==, 1);
     787                 :           5 :   data.num_free_func = 0;
     788                 :             : 
     789                 :             :   /*
     790                 :             :    * Now bring up a bus, own a name, and then start watching it.
     791                 :             :    */
     792                 :           5 :   session_bus_up ();
     793                 :             :   /* own the name */
     794                 :           5 :   own_data.num_free_func = 0;
     795                 :           5 :   own_data.num_acquired = 0;
     796                 :           5 :   own_data.num_lost = 0;
     797                 :           5 :   data.expect_null_connection = FALSE;
     798                 :           5 :   own_data.main_context = main_context;
     799                 :           5 :   owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
     800                 :             :                              name,
     801                 :             :                              G_BUS_NAME_OWNER_FLAGS_NONE,
     802                 :             :                              w_bus_acquired_handler,
     803                 :             :                              w_name_acquired_handler,
     804                 :             :                              w_name_lost_handler,
     805                 :             :                              &own_data,
     806                 :             :                              (GDestroyNotify) own_name_data_free_func);
     807                 :             : 
     808                 :          20 :   while (own_data.num_acquired < 1)
     809                 :          15 :     g_main_context_iteration (main_context, TRUE);
     810                 :             : 
     811                 :           5 :   g_assert_cmpint (own_data.num_acquired, ==, 1);
     812                 :           5 :   g_assert_cmpint (own_data.num_lost, ==, 0);
     813                 :             : 
     814                 :           5 :   connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
     815                 :           5 :   g_assert (connection != NULL);
     816                 :             : 
     817                 :             :   /* now watch the name */
     818                 :           5 :   data.num_appeared = 0;
     819                 :           5 :   data.num_vanished = 0;
     820                 :           5 :   if (watch_name_test->watch_with_closures)
     821                 :             :     {
     822                 :           2 :       id = g_bus_watch_name_on_connection_with_closures (connection,
     823                 :             :                                                          name,
     824                 :           2 :                                                          watch_name_test->watcher_flags,
     825                 :             :                                                          g_cclosure_new (G_CALLBACK (name_appeared_handler),
     826                 :             :                                                                          &data,
     827                 :             :                                                                          NULL),
     828                 :             :                                                          g_cclosure_new (G_CALLBACK (name_vanished_handler),
     829                 :             :                                                                          &data,
     830                 :             :                                                                          (GClosureNotify) watch_name_data_free_func));
     831                 :             :     }
     832                 :             :   else
     833                 :             :     {
     834                 :           3 :       id = g_bus_watch_name_on_connection (connection,
     835                 :             :                                            name,
     836                 :           3 :                                            watch_name_test->watcher_flags,
     837                 :             :                                            name_appeared_handler,
     838                 :             :                                            name_vanished_handler,
     839                 :             :                                            &data,
     840                 :             :                                            (GDestroyNotify) watch_name_data_free_func);
     841                 :             :     }
     842                 :           5 :   g_assert_cmpint (data.num_appeared, ==, 0);
     843                 :           5 :   g_assert_cmpint (data.num_vanished, ==, 0);
     844                 :             : 
     845                 :          18 :   while (data.num_appeared < 1)
     846                 :          13 :     g_main_context_iteration (main_context, TRUE);
     847                 :             : 
     848                 :           5 :   g_assert_cmpint (data.num_appeared, ==, 1);
     849                 :           5 :   g_assert_cmpint (data.num_vanished, ==, 0);
     850                 :             : 
     851                 :             :   /*
     852                 :             :    * Unwatch the name.
     853                 :             :    */
     854                 :           5 :   g_bus_unwatch_name (id);
     855                 :          10 :   while (data.num_free_func < 1)
     856                 :           5 :     g_main_context_iteration (main_context, TRUE);
     857                 :             : 
     858                 :           5 :   g_assert_cmpint (data.num_free_func, ==, 1);
     859                 :             : 
     860                 :             :   /* unown the name */
     861                 :           5 :   g_bus_unown_name (owner_id);
     862                 :          15 :   while (own_data.num_free_func < 1)
     863                 :          10 :     g_main_context_iteration (main_context, TRUE);
     864                 :             : 
     865                 :           5 :   g_assert_cmpint (own_data.num_acquired, ==, 1);
     866                 :           5 :   g_assert_cmpint (own_data.num_free_func, ==, 1);
     867                 :           5 :   own_data.num_free_func = 0;
     868                 :             :   /*
     869                 :             :    * Create a watcher and then make a name be owned.
     870                 :             :    *
     871                 :             :    * This should trigger name_appeared_handler() ...
     872                 :             :    */
     873                 :             :   /* watch the name */
     874                 :           5 :   data.num_appeared = 0;
     875                 :           5 :   data.num_vanished = 0;
     876                 :           5 :   data.num_free_func = 0;
     877                 :           5 :   if (watch_name_test->watch_with_closures)
     878                 :             :     {
     879                 :           2 :       id = g_bus_watch_name_with_closures (G_BUS_TYPE_SESSION,
     880                 :             :                                            name,
     881                 :           2 :                                            watch_name_test->watcher_flags,
     882                 :             :                                            g_cclosure_new (G_CALLBACK (name_appeared_handler),
     883                 :             :                                                            &data,
     884                 :             :                                                            NULL),
     885                 :             :                                            g_cclosure_new (G_CALLBACK (name_vanished_handler),
     886                 :             :                                                            &data,
     887                 :             :                                                            (GClosureNotify) watch_name_data_free_func));
     888                 :             :     }
     889                 :             :   else
     890                 :             :     {
     891                 :           3 :       id = g_bus_watch_name (G_BUS_TYPE_SESSION,
     892                 :             :                              name,
     893                 :           3 :                              watch_name_test->watcher_flags,
     894                 :             :                              name_appeared_handler,
     895                 :             :                              name_vanished_handler,
     896                 :             :                              &data,
     897                 :             :                              (GDestroyNotify) watch_name_data_free_func);
     898                 :             :     }
     899                 :             : 
     900                 :           5 :   g_assert_cmpint (data.num_appeared, ==, 0);
     901                 :           5 :   g_assert_cmpint (data.num_vanished, ==, 0);
     902                 :             : 
     903                 :          24 :   while (data.num_appeared == 0 && data.num_vanished == 0)
     904                 :          19 :     g_main_context_iteration (main_context, TRUE);
     905                 :             : 
     906                 :           5 :   if (watch_name_test->existing_service)
     907                 :             :     {
     908                 :           1 :       g_assert_cmpint (data.num_appeared, ==, 1);
     909                 :           1 :       g_assert_cmpint (data.num_vanished, ==, 0);
     910                 :             :     }
     911                 :             :   else
     912                 :             :     {
     913                 :           4 :       g_assert_cmpint (data.num_appeared, ==, 0);
     914                 :           4 :       g_assert_cmpint (data.num_vanished, ==, 1);
     915                 :             :     }
     916                 :             : 
     917                 :           5 :   if (!watch_name_test->existing_service)
     918                 :             :     {
     919                 :             :       /* own the name */
     920                 :           4 :       own_data.num_acquired = 0;
     921                 :           4 :       own_data.num_lost = 0;
     922                 :           4 :       own_data.expect_null_connection = FALSE;
     923                 :           4 :       own_data.main_context = main_context;
     924                 :           4 :       owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
     925                 :             :                                  name,
     926                 :             :                                  G_BUS_NAME_OWNER_FLAGS_NONE,
     927                 :             :                                  w_bus_acquired_handler,
     928                 :             :                                  w_name_acquired_handler,
     929                 :             :                                  w_name_lost_handler,
     930                 :             :                                  &own_data,
     931                 :             :                                  (GDestroyNotify) own_name_data_free_func);
     932                 :             : 
     933                 :          24 :       while (own_data.num_acquired == 0 || data.num_appeared == 0)
     934                 :          20 :         g_main_context_iteration (main_context, TRUE);
     935                 :             : 
     936                 :           4 :       g_assert_cmpint (own_data.num_acquired, ==, 1);
     937                 :           4 :       g_assert_cmpint (own_data.num_lost, ==, 0);
     938                 :           4 :       g_assert_cmpint (data.num_appeared, ==, 1);
     939                 :           4 :       g_assert_cmpint (data.num_vanished, ==, 1);
     940                 :             :     }
     941                 :             : 
     942                 :           5 :   data.expect_null_connection = TRUE;
     943                 :           5 :   if (watch_name_test->existing_service)
     944                 :             :     {
     945                 :           1 :       data.expect_null_connection = FALSE;
     946                 :           1 :       stop_service (connection, &data);
     947                 :             :     }
     948                 :           5 :   g_object_unref (connection);
     949                 :             :   /*
     950                 :             :    * Nuke the bus and check that the name vanishes and is lost.
     951                 :             :    */
     952                 :           5 :   session_bus_stop ();
     953                 :           5 :   if (!watch_name_test->existing_service)
     954                 :             :     {
     955                 :          16 :       while (own_data.num_lost < 1 || data.num_vanished < 2)
     956                 :          12 :         g_main_context_iteration (main_context, TRUE);
     957                 :           4 :       g_assert_cmpint (own_data.num_lost, ==, 1);
     958                 :           4 :       g_assert_cmpint (data.num_vanished, ==, 2);
     959                 :             :     }
     960                 :             :   else
     961                 :             :     {
     962                 :           1 :       g_assert_cmpint (own_data.num_lost, ==, 0);
     963                 :           1 :       g_assert_cmpint (data.num_vanished, ==, 1);
     964                 :             :     }
     965                 :             : 
     966                 :           5 :   g_bus_unwatch_name (id);
     967                 :          14 :   while (data.num_free_func < 1)
     968                 :           9 :     g_main_context_iteration (main_context, TRUE);
     969                 :             : 
     970                 :           5 :   g_assert_cmpint (data.num_free_func, ==, 1);
     971                 :             : 
     972                 :           5 :   if (!watch_name_test->existing_service)
     973                 :             :     {
     974                 :           4 :       g_bus_unown_name (owner_id);
     975                 :           4 :       while (own_data.num_free_func < 1)
     976                 :           0 :         g_main_context_iteration (main_context, TRUE);
     977                 :             : 
     978                 :           4 :       g_assert_cmpint (own_data.num_free_func, ==, 1);
     979                 :             :     }
     980                 :           5 :   session_bus_down ();
     981                 :           5 : }
     982                 :             : 
     983                 :             : /* ---------------------------------------------------------------------------------------------------- */
     984                 :             : 
     985                 :             : /* Called in the same thread as watcher_thread() */
     986                 :             : static void
     987                 :           2 : t_watch_name_data_free_func (WatchNameThreadData *thread_data)
     988                 :             : {
     989                 :           2 :   thread_data->data.num_free_func++;
     990                 :             : 
     991                 :           2 :   g_assert_true (g_main_context_is_owner (thread_data->thread_context));
     992                 :           2 :   g_main_context_wakeup (thread_data->thread_context);
     993                 :           2 : }
     994                 :             : 
     995                 :             : /* Called in the same thread as watcher_thread() */
     996                 :             : static void
     997                 :           2 : t_name_appeared_handler (GDBusConnection *connection,
     998                 :             :                          const gchar     *name,
     999                 :             :                          const gchar     *name_owner,
    1000                 :             :                          gpointer         user_data)
    1001                 :             : {
    1002                 :           2 :   WatchNameThreadData *thread_data = user_data;
    1003                 :           2 :   thread_data->data.num_appeared += 1;
    1004                 :             : 
    1005                 :           2 :   g_assert_true (g_main_context_is_owner (thread_data->thread_context));
    1006                 :           2 :   g_main_context_wakeup (thread_data->thread_context);
    1007                 :           2 : }
    1008                 :             : 
    1009                 :             : /* Called in the same thread as watcher_thread() */
    1010                 :             : static void
    1011                 :           1 : t_name_vanished_handler (GDBusConnection *connection,
    1012                 :             :                          const gchar     *name,
    1013                 :             :                          gpointer         user_data)
    1014                 :             : {
    1015                 :           1 :   WatchNameThreadData *thread_data = user_data;
    1016                 :           1 :   thread_data->data.num_vanished += 1;
    1017                 :             : 
    1018                 :           1 :   g_assert_true (g_main_context_is_owner (thread_data->thread_context));
    1019                 :           1 :   g_main_context_wakeup (thread_data->thread_context);
    1020                 :           1 : }
    1021                 :             : 
    1022                 :             : /* Called in the thread which constructed the GDBusConnection */
    1023                 :             : static void
    1024                 :           2 : connection_closed_cb (GDBusConnection *connection,
    1025                 :             :                       gboolean         remote_peer_vanished,
    1026                 :             :                       GError          *error,
    1027                 :             :                       gpointer         user_data)
    1028                 :             : {
    1029                 :           2 :   WatchNameThreadData *thread_data = (WatchNameThreadData *) user_data;
    1030                 :           2 :   if (thread_data->unwatch_early)
    1031                 :             :     {
    1032                 :           1 :       g_mutex_lock (&thread_data->mutex);
    1033                 :           1 :       g_bus_unwatch_name (g_atomic_int_get (&thread_data->watch_id));
    1034                 :           1 :       g_atomic_int_set (&thread_data->watch_id, 0);
    1035                 :           1 :       g_cond_signal (&thread_data->cond);
    1036                 :           1 :       g_mutex_unlock (&thread_data->mutex);
    1037                 :             :     }
    1038                 :           2 : }
    1039                 :             : 
    1040                 :             : static gpointer
    1041                 :           2 : watcher_thread (gpointer user_data)
    1042                 :             : {
    1043                 :           2 :   WatchNameThreadData *thread_data = user_data;
    1044                 :             :   GMainContext *thread_context;
    1045                 :             : 
    1046                 :           2 :   thread_context = g_main_context_new ();
    1047                 :           2 :   thread_data->thread_context = thread_context;
    1048                 :           2 :   g_main_context_push_thread_default (thread_context);
    1049                 :             : 
    1050                 :             :   // Notify that the thread has started
    1051                 :           2 :   g_mutex_lock (&thread_data->cond_mutex);
    1052                 :           2 :   g_atomic_int_set (&thread_data->started, TRUE);
    1053                 :           2 :   g_cond_signal (&thread_data->cond);
    1054                 :           2 :   g_mutex_unlock (&thread_data->cond_mutex);
    1055                 :             : 
    1056                 :             :   // Wait for the main thread to own the name before watching it
    1057                 :           2 :   g_mutex_lock (&thread_data->cond_mutex);
    1058                 :           4 :   while (!g_atomic_int_get (&thread_data->name_acquired))
    1059                 :           2 :     g_cond_wait (&thread_data->cond, &thread_data->cond_mutex);
    1060                 :           2 :   g_mutex_unlock (&thread_data->cond_mutex);
    1061                 :             : 
    1062                 :           2 :   thread_data->data.num_appeared = 0;
    1063                 :           2 :   thread_data->data.num_vanished = 0;
    1064                 :           2 :   thread_data->data.num_free_func = 0;
    1065                 :             :   // g_signal_connect_after is important to have default handler be called before our code
    1066                 :           2 :   g_signal_connect_after (thread_data->connection, "closed", G_CALLBACK (connection_closed_cb), thread_data);
    1067                 :             : 
    1068                 :           2 :   g_mutex_lock (&thread_data->mutex);
    1069                 :           2 :   thread_data->watch_id = g_bus_watch_name_on_connection (thread_data->connection,
    1070                 :             :                                                           "org.gtk.GDBus.Name1",
    1071                 :             :                                                           G_BUS_NAME_WATCHER_FLAGS_NONE,
    1072                 :             :                                                           t_name_appeared_handler,
    1073                 :             :                                                           t_name_vanished_handler,
    1074                 :             :                                                           thread_data,
    1075                 :             :                                                           (GDestroyNotify) t_watch_name_data_free_func);
    1076                 :           2 :   g_mutex_unlock (&thread_data->mutex);
    1077                 :             : 
    1078                 :           2 :   g_assert_cmpint (thread_data->data.num_appeared, ==, 0);
    1079                 :           2 :   g_assert_cmpint (thread_data->data.num_vanished, ==, 0);
    1080                 :           4 :   while (thread_data->data.num_appeared == 0)
    1081                 :           2 :     g_main_context_iteration (thread_context, TRUE);
    1082                 :           2 :   g_assert_cmpint (thread_data->data.num_appeared, ==, 1);
    1083                 :           2 :   g_assert_cmpint (thread_data->data.num_vanished, ==, 0);
    1084                 :           2 :   thread_data->data.num_appeared = 0;
    1085                 :             : 
    1086                 :             :   /* Close the connection and:
    1087                 :             :    *  - check that we had received a vanished event even begin in different thread
    1088                 :             :    *  - or check that unwatching the bus when a vanished had been scheduled
    1089                 :             :    *    make it correctly unscheduled (unwatch_early condition)
    1090                 :             :    */
    1091                 :           2 :   g_dbus_connection_close_sync (thread_data->connection, NULL, NULL);
    1092                 :           2 :   if (thread_data->unwatch_early)
    1093                 :             :     {
    1094                 :             :       // Wait for the main thread to iterate in order to have close connection handled
    1095                 :           1 :       g_mutex_lock (&thread_data->mutex);
    1096                 :           2 :       while (g_atomic_int_get (&thread_data->watch_id) != 0)
    1097                 :           1 :         g_cond_wait (&thread_data->cond, &thread_data->mutex);
    1098                 :           1 :       g_mutex_unlock (&thread_data->mutex);
    1099                 :             : 
    1100                 :           2 :       while (thread_data->data.num_free_func == 0)
    1101                 :           1 :         g_main_context_iteration (thread_context, TRUE);
    1102                 :           1 :       g_assert_cmpint (thread_data->data.num_vanished, ==, 0);
    1103                 :           1 :       g_assert_cmpint (thread_data->data.num_appeared, ==, 0);
    1104                 :           1 :       g_assert_cmpint (thread_data->data.num_free_func, ==, 1);
    1105                 :             :     }
    1106                 :             :   else
    1107                 :             :     {
    1108                 :           3 :       while (thread_data->data.num_vanished == 0)
    1109                 :             :         {
    1110                 :             :           /*
    1111                 :             :            * Close of connection is treated in the context of the thread which
    1112                 :             :            * creates the connection. We must run iteration on it (to have the 'closed'
    1113                 :             :            * signal handled) and also run current thread loop to have name_vanished
    1114                 :             :            * callback handled.
    1115                 :             :            */
    1116                 :           2 :           g_main_context_iteration (thread_context, TRUE);
    1117                 :             :         }
    1118                 :           1 :       g_assert_cmpint (thread_data->data.num_vanished, ==, 1);
    1119                 :           1 :       g_assert_cmpint (thread_data->data.num_appeared, ==, 0);
    1120                 :           1 :       g_mutex_lock (&thread_data->mutex);
    1121                 :           1 :       g_bus_unwatch_name (g_atomic_int_get (&thread_data->watch_id));
    1122                 :           1 :       g_atomic_int_set (&thread_data->watch_id, 0);
    1123                 :           1 :       g_mutex_unlock (&thread_data->mutex);
    1124                 :           1 :       while (thread_data->data.num_free_func == 0)
    1125                 :           0 :         g_main_context_iteration (thread_context, TRUE);
    1126                 :           1 :       g_assert_cmpint (thread_data->data.num_free_func, ==, 1);
    1127                 :             :     }
    1128                 :             : 
    1129                 :           2 :   g_mutex_lock (&thread_data->cond_mutex);
    1130                 :           2 :   thread_data->ended = TRUE;
    1131                 :           2 :   g_main_context_wakeup (NULL);
    1132                 :           2 :   g_cond_signal (&thread_data->cond);
    1133                 :           2 :   g_mutex_unlock (&thread_data->cond_mutex);
    1134                 :             : 
    1135                 :           2 :   g_signal_handlers_disconnect_by_func (thread_data->connection, connection_closed_cb, thread_data);
    1136                 :           2 :   g_object_unref (thread_data->connection);
    1137                 :           2 :   g_main_context_pop_thread_default (thread_context);
    1138                 :           2 :   g_main_context_unref (thread_context);
    1139                 :             : 
    1140                 :           2 :   g_mutex_lock (&thread_data->mutex);
    1141                 :           2 :   g_assert_cmpint (thread_data->watch_id, ==, 0);
    1142                 :           2 :   g_mutex_unlock (&thread_data->mutex);
    1143                 :           2 :   return NULL;
    1144                 :             : }
    1145                 :             : 
    1146                 :             : static void
    1147                 :           2 : watch_with_different_context (gboolean unwatch_early)
    1148                 :             : {
    1149                 :             :   OwnNameData own_data;
    1150                 :             :   WatchNameThreadData thread_data;
    1151                 :             :   GDBusConnection *connection;
    1152                 :             :   GThread *watcher;
    1153                 :             :   guint id;
    1154                 :           2 :   GMainContext *main_context = NULL;  /* use the global default for now */
    1155                 :             : 
    1156                 :           2 :   session_bus_up ();
    1157                 :             : 
    1158                 :           2 :   connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
    1159                 :           2 :   g_assert (connection != NULL);
    1160                 :             : 
    1161                 :           2 :   g_mutex_init (&thread_data.mutex);
    1162                 :           2 :   g_mutex_init (&thread_data.cond_mutex);
    1163                 :           2 :   g_cond_init (&thread_data.cond);
    1164                 :           2 :   thread_data.started = FALSE;
    1165                 :           2 :   thread_data.name_acquired = FALSE;
    1166                 :           2 :   thread_data.ended = FALSE;
    1167                 :           2 :   thread_data.connection = g_object_ref (connection);
    1168                 :           2 :   thread_data.unwatch_early = unwatch_early;
    1169                 :             : 
    1170                 :             :   // Create a thread which will watch a name and wait for it to be ready
    1171                 :           2 :   g_mutex_lock (&thread_data.cond_mutex);
    1172                 :           2 :   watcher = g_thread_new ("watcher", watcher_thread, &thread_data);
    1173                 :           4 :   while (!g_atomic_int_get (&thread_data.started))
    1174                 :           2 :     g_cond_wait (&thread_data.cond, &thread_data.cond_mutex);
    1175                 :           2 :   g_mutex_unlock (&thread_data.cond_mutex);
    1176                 :             : 
    1177                 :           2 :   own_data.num_acquired = 0;
    1178                 :           2 :   own_data.num_lost = 0;
    1179                 :           2 :   own_data.num_free_func = 0;
    1180                 :           2 :   own_data.expect_null_connection = FALSE;
    1181                 :           2 :   own_data.main_context = main_context;
    1182                 :             :   // Own the name to avoid direct name vanished in watcher thread
    1183                 :           2 :   id = g_bus_own_name_on_connection (connection,
    1184                 :             :                                      "org.gtk.GDBus.Name1",
    1185                 :             :                                      G_BUS_NAME_OWNER_FLAGS_REPLACE,
    1186                 :             :                                      w_name_acquired_handler,
    1187                 :             :                                      w_name_lost_handler,
    1188                 :             :                                      &own_data,
    1189                 :             :                                      (GDestroyNotify) own_name_data_free_func);
    1190                 :           6 :   while (own_data.num_acquired == 0)
    1191                 :           4 :     g_main_context_iteration (main_context, TRUE);
    1192                 :           2 :   g_assert_cmpint (own_data.num_acquired, ==, 1);
    1193                 :           2 :   g_assert_cmpint (own_data.num_lost, ==, 0);
    1194                 :             : 
    1195                 :             :   // Wake the thread for it to begin watch
    1196                 :           2 :   g_mutex_lock (&thread_data.cond_mutex);
    1197                 :           2 :   g_atomic_int_set (&thread_data.name_acquired, TRUE);
    1198                 :           2 :   g_cond_signal (&thread_data.cond);
    1199                 :           2 :   g_mutex_unlock (&thread_data.cond_mutex);
    1200                 :             : 
    1201                 :             :   // Iterate the loop until thread is waking us up
    1202                 :          10 :   while (!thread_data.ended)
    1203                 :           8 :     g_main_context_iteration (main_context, TRUE);
    1204                 :             : 
    1205                 :           2 :   g_thread_join (watcher);
    1206                 :             : 
    1207                 :           2 :   g_bus_unown_name (id);
    1208                 :           2 :   while (own_data.num_free_func == 0)
    1209                 :           0 :     g_main_context_iteration (main_context, TRUE);
    1210                 :           2 :   g_assert_cmpint (own_data.num_free_func, ==, 1);
    1211                 :             : 
    1212                 :           2 :   g_mutex_clear (&thread_data.mutex);
    1213                 :           2 :   g_mutex_clear (&thread_data.cond_mutex);
    1214                 :           2 :   g_cond_clear (&thread_data.cond);
    1215                 :             : 
    1216                 :           2 :   session_bus_stop ();
    1217                 :           2 :   g_assert_true (g_dbus_connection_is_closed (connection));
    1218                 :           2 :   g_object_unref (connection);
    1219                 :           2 :   session_bus_down ();
    1220                 :           2 : }
    1221                 :             : 
    1222                 :             : static void
    1223                 :           1 : test_bus_watch_different_context (void)
    1224                 :             : {
    1225                 :           1 :   watch_with_different_context (FALSE);
    1226                 :           1 : }
    1227                 :             : 
    1228                 :             : /* ---------------------------------------------------------------------------------------------------- */
    1229                 :             : 
    1230                 :             : static void
    1231                 :           1 : test_bus_unwatch_early (void)
    1232                 :             : {
    1233                 :           1 :   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/604");
    1234                 :           1 :   watch_with_different_context (TRUE);
    1235                 :           1 : }
    1236                 :             : 
    1237                 :             : /* ---------------------------------------------------------------------------------------------------- */
    1238                 :             : 
    1239                 :             : static void
    1240                 :           1 : test_validate_names (void)
    1241                 :             : {
    1242                 :             :   guint n;
    1243                 :             :   static const struct
    1244                 :             :   {
    1245                 :             :     gboolean name;
    1246                 :             :     gboolean unique;
    1247                 :             :     gboolean interface;
    1248                 :             :     const gchar *string;
    1249                 :             :   } names[] = {
    1250                 :             :     { 1, 0, 1, "valid.well_known.name"},
    1251                 :             :     { 1, 0, 0, "valid.well-known.name"},
    1252                 :             :     { 1, 1, 0, ":valid.unique.name"},
    1253                 :             :     { 0, 0, 0, "invalid.5well_known.name"},
    1254                 :             :     { 0, 0, 0, "4invalid.5well_known.name"},
    1255                 :             :     { 1, 1, 0, ":4valid.5unique.name"},
    1256                 :             :     { 0, 0, 0, ""},
    1257                 :             :     { 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 */
    1258                 :             :     { 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! */
    1259                 :             :     { 0, 0, 0, ".starts.with.a.dot"},
    1260                 :             :     { 0, 0, 0, "contains.invalid;.characters"},
    1261                 :             :     { 0, 0, 0, "contains.inva/lid.characters"},
    1262                 :             :     { 0, 0, 0, "contains.inva[lid.characters"},
    1263                 :             :     { 0, 0, 0, "contains.inva]lid.characters"},
    1264                 :             :     { 0, 0, 0, "contains.inva_æøå_lid.characters"},
    1265                 :             :     { 1, 1, 0, ":1.1"},
    1266                 :             :   };
    1267                 :             : 
    1268                 :          17 :   for (n = 0; n < G_N_ELEMENTS (names); n++)
    1269                 :             :     {
    1270                 :          16 :       if (names[n].name)
    1271                 :           6 :         g_assert (g_dbus_is_name (names[n].string));
    1272                 :             :       else
    1273                 :          10 :         g_assert (!g_dbus_is_name (names[n].string));
    1274                 :             : 
    1275                 :          16 :       if (names[n].unique)
    1276                 :           3 :         g_assert (g_dbus_is_unique_name (names[n].string));
    1277                 :             :       else
    1278                 :          13 :         g_assert (!g_dbus_is_unique_name (names[n].string));
    1279                 :             : 
    1280                 :          16 :       if (names[n].interface)
    1281                 :             :         {
    1282                 :           2 :           g_assert (g_dbus_is_interface_name (names[n].string));
    1283                 :           2 :           g_assert (g_dbus_is_error_name (names[n].string)); 
    1284                 :             :         }
    1285                 :             :       else
    1286                 :             :         {
    1287                 :          14 :           g_assert (!g_dbus_is_interface_name (names[n].string));
    1288                 :          14 :           g_assert (!g_dbus_is_error_name (names[n].string));
    1289                 :             :         }        
    1290                 :             :     }
    1291                 :           1 : }
    1292                 :             : 
    1293                 :             : static void
    1294                 :          10 : assert_cmp_escaped_object_path (const gchar *s,
    1295                 :             :                                 const gchar *correct_escaped)
    1296                 :             : {
    1297                 :             :   gchar *escaped;
    1298                 :             :   guint8 *unescaped;
    1299                 :             : 
    1300                 :          10 :   escaped = g_dbus_escape_object_path (s);
    1301                 :          10 :   g_assert_cmpstr (escaped, ==, correct_escaped);
    1302                 :             : 
    1303                 :          10 :   g_free (escaped);
    1304                 :          10 :   escaped = g_dbus_escape_object_path_bytestring ((const guint8 *) s);
    1305                 :          10 :   g_assert_cmpstr (escaped, ==, correct_escaped);
    1306                 :             : 
    1307                 :          10 :   unescaped = g_dbus_unescape_object_path (escaped);
    1308                 :          10 :   g_assert_cmpstr ((const gchar *) unescaped, ==, s);
    1309                 :             : 
    1310                 :          10 :   g_free (escaped);
    1311                 :          10 :   g_free (unescaped);
    1312                 :          10 : }
    1313                 :             : 
    1314                 :             : static void
    1315                 :           1 : test_escape_object_path (void)
    1316                 :             : {
    1317                 :           1 :   assert_cmp_escaped_object_path ("Foo42", "Foo42");
    1318                 :           1 :   assert_cmp_escaped_object_path ("foo.bar.baz", "foo_2ebar_2ebaz");
    1319                 :           1 :   assert_cmp_escaped_object_path ("foo_bar_baz", "foo_5fbar_5fbaz");
    1320                 :           1 :   assert_cmp_escaped_object_path ("_", "_5f");
    1321                 :           1 :   assert_cmp_escaped_object_path ("__", "_5f_5f");
    1322                 :           1 :   assert_cmp_escaped_object_path ("", "_");
    1323                 :           1 :   assert_cmp_escaped_object_path (":1.42", "_3a1_2e42");
    1324                 :           1 :   assert_cmp_escaped_object_path ("a/b", "a_2fb");
    1325                 :           1 :   assert_cmp_escaped_object_path (" ", "_20");
    1326                 :           1 :   assert_cmp_escaped_object_path ("\n", "_0a");
    1327                 :             : 
    1328                 :           1 :   g_assert_null (g_dbus_unescape_object_path ("_ii"));
    1329                 :           1 :   g_assert_null (g_dbus_unescape_object_path ("döner"));
    1330                 :           1 :   g_assert_null (g_dbus_unescape_object_path ("_00"));
    1331                 :           1 :   g_assert_null (g_dbus_unescape_object_path ("_61"));
    1332                 :           1 :   g_assert_null (g_dbus_unescape_object_path ("_ga"));
    1333                 :           1 :   g_assert_null (g_dbus_unescape_object_path ("_ag"));
    1334                 :           1 : }
    1335                 :             : 
    1336                 :             : /* ---------------------------------------------------------------------------------------------------- */
    1337                 :             : 
    1338                 :             : int
    1339                 :           1 : main (int   argc,
    1340                 :             :       char *argv[])
    1341                 :             : {
    1342                 :             :   gint ret;
    1343                 :             : 
    1344                 :           1 :   g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
    1345                 :             : 
    1346                 :           1 :   g_test_dbus_unset ();
    1347                 :             : 
    1348                 :           1 :   g_test_add_func ("/gdbus/validate-names", test_validate_names);
    1349                 :           1 :   g_test_add_func ("/gdbus/bus-own-name", test_bus_own_name);
    1350                 :           1 :   g_test_add_data_func ("/gdbus/bus-watch-name",
    1351                 :             :                         &watch_no_closures_no_flags,
    1352                 :             :                         test_bus_watch_name);
    1353                 :           1 :   g_test_add_data_func ("/gdbus/bus-watch-name-auto-start",
    1354                 :             :                         &watch_no_closures_flags_auto_start,
    1355                 :             :                         test_bus_watch_name);
    1356                 :           1 :   g_test_add_data_func ("/gdbus/bus-watch-name-auto-start-service-exist",
    1357                 :             :                         &watch_no_closures_flags_auto_start_service_exist,
    1358                 :             :                         test_bus_watch_name);
    1359                 :           1 :   g_test_add_data_func ("/gdbus/bus-watch-name-closures",
    1360                 :             :                         &watch_closures_no_flags,
    1361                 :             :                         test_bus_watch_name);
    1362                 :           1 :   g_test_add_data_func ("/gdbus/bus-watch-name-closures-auto-start",
    1363                 :             :                         &watch_closures_flags_auto_start,
    1364                 :             :                         test_bus_watch_name);
    1365                 :           1 :   g_test_add_func ("/gdbus/bus-watch-different-context", test_bus_watch_different_context);
    1366                 :           1 :   g_test_add_func ("/gdbus/bus-unwatch-early", test_bus_unwatch_early);
    1367                 :           1 :   g_test_add_func ("/gdbus/escape-object-path", test_escape_object_path);
    1368                 :           1 :   ret = g_test_run();
    1369                 :             : 
    1370                 :           1 :   return ret;
    1371                 :             : }
        

Generated by: LCOV version 2.0-1