LCOV - code coverage report
Current view: top level - glib/gio/tests - gdbus-names.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 635 640 99.2 %
Date: 2024-04-23 05:16:05 Functions: 25 25 100.0 %
Branches: 129 138 93.5 %

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

Generated by: LCOV version 1.14