(root)/
glib-2.79.0/
gio/
gtestdbus.c
       1  /* GIO testing utilities
       2   *
       3   * Copyright (C) 2008-2010 Red Hat, Inc.
       4   * Copyright (C) 2012 Collabora Ltd. <http://www.collabora.co.uk/>
       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   * Authors: David Zeuthen <davidz@redhat.com>
      22   *          Xavier Claessens <xavier.claessens@collabora.co.uk>
      23   */
      24  
      25  #include "config.h"
      26  
      27  #include <stdlib.h>
      28  #include <stdio.h>
      29  #include <errno.h>
      30  #include <string.h>
      31  #include <gstdio.h>
      32  #ifdef G_OS_UNIX
      33  #include <unistd.h>
      34  #endif
      35  #ifdef G_OS_WIN32
      36  #include <io.h>
      37  #include <fcntl.h>
      38  #include <windows.h>
      39  #endif
      40  
      41  #include <glib.h>
      42  
      43  #include "gdbusconnection.h"
      44  #include "gdbusprivate.h"
      45  #include "gfile.h"
      46  #include "gioenumtypes.h"
      47  #include "gtestdbus.h"
      48  
      49  #include "glibintl.h"
      50  
      51  #ifdef G_OS_UNIX
      52  #include "glib-unix.h"
      53  #include "glib-unixprivate.h"
      54  #endif
      55  
      56  /* -------------------------------------------------------------------------- */
      57  /* Utility: Wait until object has a single ref  */
      58  
      59  typedef struct
      60  {
      61    GMainLoop *loop;
      62    gboolean   timed_out;
      63  } WeakNotifyData;
      64  
      65  static void
      66  on_weak_notify_timeout (gpointer user_data)
      67  {
      68    WeakNotifyData *data = user_data;
      69    data->timed_out = TRUE;
      70    g_main_loop_quit (data->loop);
      71  }
      72  
      73  static gboolean
      74  unref_on_idle (gpointer object)
      75  {
      76    g_object_unref (object);
      77    return FALSE;
      78  }
      79  
      80  static gboolean
      81  _g_object_unref_and_wait_weak_notify (gpointer object)
      82  {
      83    WeakNotifyData data;
      84    guint timeout_id;
      85  
      86    data.loop = g_main_loop_new (NULL, FALSE);
      87    data.timed_out = FALSE;
      88  
      89    g_object_weak_ref (object, (GWeakNotify) g_main_loop_quit, data.loop);
      90  
      91    /* Drop the strong ref held by the caller in an idle callback. This is to
      92     * make sure the mainloop is already running when weak notify happens (when
      93     * all other strong ref holders have dropped theirs). */
      94    g_idle_add (unref_on_idle, object);
      95  
      96    /* Make sure we don't block forever */
      97    timeout_id = g_timeout_add_seconds_once (30, on_weak_notify_timeout, &data);
      98  
      99    g_main_loop_run (data.loop);
     100  
     101    if (data.timed_out)
     102      {
     103        g_warning ("Weak notify timeout, object ref_count=%d",
     104            G_OBJECT (object)->ref_count);
     105      }
     106    else
     107      {
     108        g_source_remove (timeout_id);
     109      }
     110  
     111    g_main_loop_unref (data.loop);
     112    return data.timed_out;
     113  }
     114  
     115  /* -------------------------------------------------------------------------- */
     116  /* Utilities to cleanup the mess in the case unit test process crash */
     117  
     118  #ifdef G_OS_WIN32
     119  
     120  /* This could be interesting to expose in public API */
     121  static void
     122  _g_test_watcher_add_pid (GPid pid)
     123  {
     124    HANDLE job = NULL;
     125  
     126    if (g_once_init_enter (&job))
     127      {
     128        JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
     129  
     130        HANDLE tmp = CreateJobObjectW (NULL, NULL);
     131        memset (&info, 0, sizeof (info));
     132        info.BasicLimitInformation.LimitFlags = 0x2000 /* JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE */;
     133  
     134        if (!SetInformationJobObject (tmp, JobObjectExtendedLimitInformation, &info, sizeof (info)))
     135          g_warning ("Can't enable JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE: %s", g_win32_error_message (GetLastError()));
     136  
     137        g_once_init_leave_pointer (&job, tmp);
     138      }
     139  
     140    if (!AssignProcessToJobObject(job, pid))
     141      g_warning ("Can't assign process to job: %s", g_win32_error_message (GetLastError()));
     142  }
     143  
     144  static void
     145  _g_test_watcher_remove_pid (GPid pid)
     146  {
     147    /* No need to unassign the process from the job object as the process
     148       will be killed anyway */
     149  }
     150  
     151  #else
     152  
     153  #define ADD_PID_FORMAT "add pid %d\n"
     154  #define REMOVE_PID_FORMAT "remove pid %d\n"
     155  
     156  static void
     157  watch_parent (gint fd)
     158  {
     159    GIOChannel *channel;
     160    GPollFD fds[1];
     161    GArray *pids_to_kill;
     162  
     163    channel = g_io_channel_unix_new (fd);
     164  
     165    fds[0].fd = fd;
     166    fds[0].events = G_IO_HUP | G_IO_IN;
     167    fds[0].revents = 0;
     168  
     169    pids_to_kill = g_array_new (FALSE, FALSE, sizeof (guint));
     170  
     171    do
     172      {
     173        gint num_events;
     174        gchar *command = NULL;
     175        guint pid;
     176        guint n;
     177        GError *error = NULL;
     178  
     179        num_events = g_poll (fds, 1, -1);
     180        if (num_events == 0)
     181          continue;
     182  
     183        if (fds[0].revents & G_IO_HUP)
     184          {
     185            /* Parent quit, cleanup the mess and exit */
     186            for (n = 0; n < pids_to_kill->len; n++)
     187              {
     188                pid = g_array_index (pids_to_kill, guint, n);
     189                g_printerr ("cleaning up pid %d\n", pid);
     190                kill (pid, SIGTERM);
     191              }
     192  
     193            g_array_unref (pids_to_kill);
     194            g_io_channel_shutdown (channel, FALSE, &error);
     195            g_assert_no_error (error);
     196            g_io_channel_unref (channel);
     197  
     198            exit (0);
     199          }
     200  
     201        /* Read the command from the input */
     202        g_io_channel_read_line (channel, &command, NULL, NULL, &error);
     203        g_assert_no_error (error);
     204  
     205        /* Check for known commands */
     206        if (sscanf (command, ADD_PID_FORMAT, &pid) == 1)
     207          {
     208            g_array_append_val (pids_to_kill, pid);
     209          }
     210        else if (sscanf (command, REMOVE_PID_FORMAT, &pid) == 1)
     211          {
     212            for (n = 0; n < pids_to_kill->len; n++)
     213              {
     214                if (g_array_index (pids_to_kill, guint, n) == pid)
     215                  {
     216                    g_array_remove_index (pids_to_kill, n);
     217                    pid = 0;
     218                    break;
     219                  }
     220              }
     221            if (pid != 0)
     222              {
     223                g_warning ("unknown pid %d to remove", pid);
     224              }
     225          }
     226        else
     227          {
     228            g_warning ("unknown command from parent '%s'", command);
     229          }
     230  
     231        g_free (command);
     232      }
     233    while (TRUE);
     234  }
     235  
     236  static GIOChannel *
     237  watcher_init (void)
     238  {
     239    static gsize started = 0;
     240    static GIOChannel *channel = NULL;
     241    int errsv;
     242  
     243    if (g_once_init_enter (&started))
     244      {
     245        gint pipe_fds[2];
     246  
     247        /* fork a child to clean up when we are killed */
     248        if (!g_unix_open_pipe_internal (pipe_fds, TRUE, FALSE))
     249          {
     250            errsv = errno;
     251            g_warning ("pipe() failed: %s", g_strerror (errsv));
     252            g_assert_not_reached ();
     253          }
     254  
     255        /* flush streams to avoid buffers being duplicated in the child and
     256         * flushed by both the child and parent later
     257         *
     258         * FIXME: This is a workaround for the fact that watch_parent() uses
     259         * non-async-signal-safe API. See
     260         * https://gitlab.gnome.org/GNOME/glib/-/issues/2322#note_1034330
     261         */
     262        fflush (stdout);
     263        fflush (stderr);
     264  
     265        switch (fork ())
     266          {
     267          case -1:
     268            errsv = errno;
     269            g_warning ("fork() failed: %s", g_strerror (errsv));
     270            g_assert_not_reached ();
     271            break;
     272  
     273          case 0:
     274            /* child */
     275            close (pipe_fds[1]);
     276            watch_parent (pipe_fds[0]);
     277            break;
     278  
     279          default:
     280            /* parent */
     281            close (pipe_fds[0]);
     282            channel = g_io_channel_unix_new (pipe_fds[1]);
     283          }
     284  
     285        g_once_init_leave (&started, 1);
     286      }
     287  
     288    return channel;
     289  }
     290  
     291  static void
     292  watcher_send_command (const gchar *command)
     293  {
     294    GIOChannel *channel;
     295    GError *error = NULL;
     296    GIOStatus status;
     297  
     298    channel = watcher_init ();
     299  
     300    do
     301     status = g_io_channel_write_chars (channel, command, -1, NULL, &error);
     302    while (status == G_IO_STATUS_AGAIN);
     303    g_assert_no_error (error);
     304  
     305    g_io_channel_flush (channel, &error);
     306    g_assert_no_error (error);
     307  }
     308  
     309  /* This could be interesting to expose in public API */
     310  static void
     311  _g_test_watcher_add_pid (GPid pid)
     312  {
     313    gchar *command;
     314  
     315    command = g_strdup_printf (ADD_PID_FORMAT, (guint) pid);
     316    watcher_send_command (command);
     317    g_free (command);
     318  }
     319  
     320  static void
     321  _g_test_watcher_remove_pid (GPid pid)
     322  {
     323    gchar *command;
     324  
     325    command = g_strdup_printf (REMOVE_PID_FORMAT, (guint) pid);
     326    watcher_send_command (command);
     327    g_free (command);
     328  }
     329  
     330  #endif
     331  
     332  /* -------------------------------------------------------------------------- */
     333  /* GTestDBus object implementation */
     334  
     335  /**
     336   * GTestDBus:
     337   *
     338   * A helper class for testing code which uses D-Bus without touching the user’s
     339   * session bus.
     340   *
     341   * Note that `GTestDBus` modifies the user’s environment, calling
     342   * [`setenv()`](man:setenv(3)). This is not thread-safe, so all `GTestDBus`
     343   * calls should be completed before threads are spawned, or should have
     344   * appropriate locking to ensure no access conflicts to environment variables
     345   * shared between `GTestDBus` and other threads.
     346   *
     347   * ## Creating unit tests using `GTestDBus`
     348   * 
     349   * Testing of D-Bus services can be tricky because normally we only ever run
     350   * D-Bus services over an existing instance of the D-Bus daemon thus we
     351   * usually don’t activate D-Bus services that are not yet installed into the
     352   * target system. The `GTestDBus` object makes this easier for us by taking care
     353   * of the lower level tasks such as running a private D-Bus daemon and looking
     354   * up uninstalled services in customizable locations, typically in your source
     355   * code tree.
     356   *
     357   * The first thing you will need is a separate service description file for the
     358   * D-Bus daemon. Typically a `services` subdirectory of your `tests` directory
     359   * is a good place to put this file.
     360   *
     361   * The service file should list your service along with an absolute path to the
     362   * uninstalled service executable in your source tree. Using autotools we would
     363   * achieve this by adding a file such as `my-server.service.in` in the services
     364   * directory and have it processed by configure.
     365   *
     366   * ```
     367   * [D-BUS Service]
     368   * Name=org.gtk.GDBus.Examples.ObjectManager
     369   * Exec=@abs_top_builddir@/gio/tests/gdbus-example-objectmanager-server
     370   * ```
     371   *
     372   * You will also need to indicate this service directory in your test
     373   * fixtures, so you will need to pass the path while compiling your
     374   * test cases. Typically this is done with autotools with an added
     375   * preprocessor flag specified to compile your tests such as:
     376   *
     377   * ```
     378   * -DTEST_SERVICES=\""$(abs_top_builddir)/tests/services"\"
     379   * ```
     380   *
     381   * Once you have a service definition file which is local to your source tree,
     382   * you can proceed to set up a GTest fixture using the `GTestDBus` scaffolding.
     383   *
     384   * An example of a test fixture for D-Bus services can be found
     385   * here:
     386   * [gdbus-test-fixture.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-test-fixture.c)
     387   *
     388   * Note that these examples only deal with isolating the D-Bus aspect of your
     389   * service. To successfully run isolated unit tests on your service you may need
     390   * some additional modifications to your test case fixture. For example; if your
     391   * service uses [class@Gio.Settings] and installs a schema then it is important
     392   * that your test service not load the schema in the ordinary installed location
     393   * (chances are that your service and schema files are not yet installed, or
     394   * worse; there is an older version of the schema file sitting in the install
     395   * location).
     396   *
     397   * Most of the time we can work around these obstacles using the
     398   * environment. Since the environment is inherited by the D-Bus daemon
     399   * created by `GTestDBus` and then in turn inherited by any services the
     400   * D-Bus daemon activates, using the setup routine for your fixture is
     401   * a practical place to help sandbox your runtime environment. For the
     402   * rather typical GSettings case we can work around this by setting
     403   * `GSETTINGS_SCHEMA_DIR` to the in tree directory holding your schemas
     404   * in the above `fixture_setup()` routine.
     405   *
     406   * The GSettings schemas need to be locally pre-compiled for this to work. This
     407   * can be achieved by compiling the schemas locally as a step before running
     408   * test cases, an autotools setup might do the following in the directory
     409   * holding schemas:
     410   *
     411   * ```
     412   *     all-am:
     413   *             $(GLIB_COMPILE_SCHEMAS) .
     414   *
     415   *     CLEANFILES += gschemas.compiled
     416   * ```
     417   *
     418   * Since: 2.34
     419   */
     420  
     421  typedef struct _GTestDBusClass   GTestDBusClass;
     422  typedef struct _GTestDBusPrivate GTestDBusPrivate;
     423  
     424  struct _GTestDBus {
     425    GObject parent;
     426  
     427    GTestDBusPrivate *priv;
     428  };
     429  
     430  struct _GTestDBusClass {
     431    GObjectClass parent_class;
     432  };
     433  
     434  struct _GTestDBusPrivate
     435  {
     436    GTestDBusFlags flags;
     437    GPtrArray *service_dirs;
     438    GPid bus_pid;
     439    gchar *bus_address;
     440    gboolean up;
     441  };
     442  
     443  enum
     444  {
     445    PROP_0,
     446    PROP_FLAGS,
     447  };
     448  
     449  G_DEFINE_TYPE_WITH_PRIVATE (GTestDBus, g_test_dbus, G_TYPE_OBJECT)
     450  
     451  static void
     452  g_test_dbus_init (GTestDBus *self)
     453  {
     454    self->priv = g_test_dbus_get_instance_private (self);
     455    self->priv->service_dirs = g_ptr_array_new_with_free_func (g_free);
     456  }
     457  
     458  static void
     459  g_test_dbus_dispose (GObject *object)
     460  {
     461    GTestDBus *self = (GTestDBus *) object;
     462  
     463    if (self->priv->up)
     464      g_test_dbus_down (self);
     465  
     466    G_OBJECT_CLASS (g_test_dbus_parent_class)->dispose (object);
     467  }
     468  
     469  static void
     470  g_test_dbus_finalize (GObject *object)
     471  {
     472    GTestDBus *self = (GTestDBus *) object;
     473  
     474    g_ptr_array_unref (self->priv->service_dirs);
     475    g_free (self->priv->bus_address);
     476  
     477    G_OBJECT_CLASS (g_test_dbus_parent_class)->finalize (object);
     478  }
     479  
     480  static void
     481  g_test_dbus_get_property (GObject *object,
     482      guint property_id,
     483      GValue *value,
     484      GParamSpec *pspec)
     485  {
     486    GTestDBus *self = (GTestDBus *) object;
     487  
     488    switch (property_id)
     489      {
     490        case PROP_FLAGS:
     491          g_value_set_flags (value, g_test_dbus_get_flags (self));
     492          break;
     493        default:
     494          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     495          break;
     496      }
     497  }
     498  
     499  static void
     500  g_test_dbus_set_property (GObject *object,
     501      guint property_id,
     502      const GValue *value,
     503      GParamSpec *pspec)
     504  {
     505    GTestDBus *self = (GTestDBus *) object;
     506  
     507    switch (property_id)
     508      {
     509        case PROP_FLAGS:
     510          self->priv->flags = g_value_get_flags (value);
     511          break;
     512        default:
     513          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     514          break;
     515      }
     516  }
     517  
     518  static void
     519  g_test_dbus_class_init (GTestDBusClass *klass)
     520  {
     521    GObjectClass *object_class = G_OBJECT_CLASS (klass);
     522  
     523    object_class->dispose = g_test_dbus_dispose;
     524    object_class->finalize = g_test_dbus_finalize;
     525    object_class->get_property = g_test_dbus_get_property;
     526    object_class->set_property = g_test_dbus_set_property;
     527  
     528    /**
     529     * GTestDBus:flags:
     530     *
     531     * #GTestDBusFlags specifying the behaviour of the D-Bus session.
     532     *
     533     * Since: 2.34
     534     */
     535    g_object_class_install_property (object_class, PROP_FLAGS,
     536      g_param_spec_flags ("flags", NULL, NULL,
     537                          G_TYPE_TEST_DBUS_FLAGS, G_TEST_DBUS_NONE,
     538                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
     539                          G_PARAM_STATIC_STRINGS));
     540  
     541  }
     542  
     543  static gchar *
     544  write_config_file (GTestDBus *self)
     545  {
     546    GString *contents;
     547    gint fd;
     548    guint i;
     549    GError *error = NULL;
     550    gchar *path = NULL;
     551  
     552    fd = g_file_open_tmp ("g-test-dbus-XXXXXX", &path, &error);
     553    g_assert_no_error (error);
     554  
     555    contents = g_string_new (NULL);
     556    g_string_append (contents,
     557        "<busconfig>\n"
     558        "  <type>session</type>\n"
     559  #ifdef G_OS_WIN32
     560        "  <listen>nonce-tcp:</listen>\n"
     561  #else
     562        "  <listen>unix:tmpdir=/tmp</listen>\n"
     563  #endif
     564  		   );
     565  
     566    for (i = 0; i < self->priv->service_dirs->len; i++)
     567      {
     568        const gchar *dir_path = g_ptr_array_index (self->priv->service_dirs, i);
     569  
     570        g_string_append_printf (contents,
     571            "  <servicedir>%s</servicedir>\n", dir_path);
     572      }
     573  
     574    g_string_append (contents,
     575        "  <policy context=\"default\">\n"
     576        "    <!-- Allow everything to be sent -->\n"
     577        "    <allow send_destination=\"*\" eavesdrop=\"true\"/>\n"
     578        "    <!-- Allow everything to be received -->\n"
     579        "    <allow eavesdrop=\"true\"/>\n"
     580        "    <!-- Allow anyone to own anything -->\n"
     581        "    <allow own=\"*\"/>\n"
     582        "  </policy>\n"
     583        "</busconfig>\n");
     584  
     585    close (fd);
     586    g_file_set_contents_full (path, contents->str, contents->len,
     587                              G_FILE_SET_CONTENTS_NONE,
     588                              0600, &error);
     589    g_assert_no_error (error);
     590  
     591    g_string_free (contents, TRUE);
     592  
     593    return path;
     594  }
     595  
     596  static gboolean
     597  make_pipe (gint     pipe_fds[2],
     598             GError **error)
     599  {
     600  #if defined(G_OS_UNIX)
     601    return g_unix_open_pipe (pipe_fds, O_CLOEXEC, error);
     602  #elif defined(G_OS_WIN32)
     603    if (_pipe (pipe_fds, 4096, _O_BINARY) < 0)
     604      {
     605        int errsv = errno;
     606  
     607        g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
     608                     _("Failed to create pipe for communicating with child process (%s)"),
     609                     g_strerror (errsv));
     610        return FALSE;
     611      }
     612    return TRUE;
     613  #else
     614    g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
     615                 _("Pipes are not supported in this platform"));
     616    return FALSE;
     617  #endif
     618  }
     619  
     620  static void
     621  start_daemon (GTestDBus *self)
     622  {
     623    const gchar *argv[] = {"dbus-daemon", "--print-address", "--config-file=foo", NULL};
     624    gint pipe_fds[2] = {-1, -1};
     625    gchar *config_path;
     626    gchar *config_arg;
     627    gchar *print_address;
     628    GIOChannel *channel;
     629    gsize termpos;
     630    GError *error = NULL;
     631  
     632    if (g_getenv ("G_TEST_DBUS_DAEMON") != NULL)
     633      argv[0] = (gchar *)g_getenv ("G_TEST_DBUS_DAEMON");
     634  
     635    make_pipe (pipe_fds, &error);
     636    g_assert_no_error (error);
     637  
     638    print_address = g_strdup_printf ("--print-address=%d", pipe_fds[1]);
     639    argv[1] = print_address;
     640    g_assert_no_error (error);
     641  
     642    /* Write config file and set its path in argv */
     643    config_path = write_config_file (self);
     644    config_arg = g_strdup_printf ("--config-file=%s", config_path);
     645    argv[2] = config_arg;
     646  
     647    /* Spawn dbus-daemon */
     648    g_spawn_async_with_pipes_and_fds (NULL,
     649                                      argv,
     650                                      NULL,
     651                                      /* We Need this to get the pid returned on win32 */
     652                                      G_SPAWN_DO_NOT_REAP_CHILD |
     653                                      G_SPAWN_SEARCH_PATH |
     654                                      /* dbus-daemon will not abuse our descriptors, and
     655                                       * passing this means we can use posix_spawn() for speed */
     656                                      G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
     657                                      NULL, NULL,
     658                                      -1, -1, -1,
     659                                      &pipe_fds[1], &pipe_fds[1], 1,
     660                                      &self->priv->bus_pid,
     661                                      NULL, NULL, NULL,
     662                                      &error);
     663    g_assert_no_error (error);
     664  
     665    _g_test_watcher_add_pid (self->priv->bus_pid);
     666  
     667    /* Read bus address from pipe */
     668    channel = g_io_channel_unix_new (pipe_fds[0]);
     669    pipe_fds[0] = -1;
     670    g_io_channel_set_close_on_unref (channel, TRUE);
     671    g_io_channel_read_line (channel, &self->priv->bus_address, NULL,
     672        &termpos, &error);
     673    g_assert_no_error (error);
     674    self->priv->bus_address[termpos] = '\0';
     675    close (pipe_fds[1]);
     676    pipe_fds[1] = -1;
     677  
     678    /* start dbus-monitor */
     679    if (g_getenv ("G_DBUS_MONITOR") != NULL)
     680      {
     681        gchar *command;
     682  
     683        command = g_strdup_printf ("dbus-monitor --address %s",
     684            self->priv->bus_address);
     685        g_spawn_command_line_async (command, NULL);
     686        g_free (command);
     687  
     688        g_usleep (500 * 1000);
     689      }
     690  
     691    /* Cleanup */
     692    g_io_channel_shutdown (channel, FALSE, &error);
     693    g_assert_no_error (error);
     694    g_io_channel_unref (channel);
     695  
     696    /* Don't use g_file_delete since it calls into gvfs */
     697    if (g_unlink (config_path) != 0)
     698      g_assert_not_reached ();
     699  
     700    g_free (print_address);
     701    g_free (config_path);
     702    g_free (config_arg);
     703  }
     704  
     705  static void
     706  stop_daemon (GTestDBus *self)
     707  {
     708  #ifdef G_OS_WIN32
     709    if (!TerminateProcess (self->priv->bus_pid, 0))
     710      g_warning ("Can't terminate process: %s", g_win32_error_message (GetLastError()));
     711  #else
     712    kill (self->priv->bus_pid, SIGTERM);
     713  #endif
     714    _g_test_watcher_remove_pid (self->priv->bus_pid);
     715    g_spawn_close_pid (self->priv->bus_pid);
     716    self->priv->bus_pid = 0;
     717  
     718    g_free (self->priv->bus_address);
     719    self->priv->bus_address = NULL;
     720  }
     721  
     722  /**
     723   * g_test_dbus_new:
     724   * @flags: a #GTestDBusFlags
     725   *
     726   * Create a new #GTestDBus object.
     727   *
     728   * Returns: (transfer full): a new #GTestDBus.
     729   */
     730  GTestDBus *
     731  g_test_dbus_new (GTestDBusFlags flags)
     732  {
     733    return g_object_new (G_TYPE_TEST_DBUS,
     734        "flags", flags,
     735        NULL);
     736  }
     737  
     738  /**
     739   * g_test_dbus_get_flags:
     740   * @self: a #GTestDBus
     741   *
     742   * Get the flags of the #GTestDBus object.
     743   *
     744   * Returns: the value of #GTestDBus:flags property
     745   */
     746  GTestDBusFlags
     747  g_test_dbus_get_flags (GTestDBus *self)
     748  {
     749    g_return_val_if_fail (G_IS_TEST_DBUS (self), G_TEST_DBUS_NONE);
     750  
     751    return self->priv->flags;
     752  }
     753  
     754  /**
     755   * g_test_dbus_get_bus_address:
     756   * @self: a #GTestDBus
     757   *
     758   * Get the address on which dbus-daemon is running. If g_test_dbus_up() has not
     759   * been called yet, %NULL is returned. This can be used with
     760   * g_dbus_connection_new_for_address().
     761   *
     762   * Returns: (nullable): the address of the bus, or %NULL.
     763   */
     764  const gchar *
     765  g_test_dbus_get_bus_address (GTestDBus *self)
     766  {
     767    g_return_val_if_fail (G_IS_TEST_DBUS (self), NULL);
     768  
     769    return self->priv->bus_address;
     770  }
     771  
     772  /**
     773   * g_test_dbus_add_service_dir:
     774   * @self: a #GTestDBus
     775   * @path: path to a directory containing .service files
     776   *
     777   * Add a path where dbus-daemon will look up .service files. This can't be
     778   * called after g_test_dbus_up().
     779   */
     780  void
     781  g_test_dbus_add_service_dir (GTestDBus *self,
     782      const gchar *path)
     783  {
     784    g_return_if_fail (G_IS_TEST_DBUS (self));
     785    g_return_if_fail (self->priv->bus_address == NULL);
     786  
     787    g_ptr_array_add (self->priv->service_dirs, g_strdup (path));
     788  }
     789  
     790  /**
     791   * g_test_dbus_up:
     792   * @self: a #GTestDBus
     793   *
     794   * Start a dbus-daemon instance and set DBUS_SESSION_BUS_ADDRESS. After this
     795   * call, it is safe for unit tests to start sending messages on the session bus.
     796   *
     797   * If this function is called from setup callback of g_test_add(),
     798   * g_test_dbus_down() must be called in its teardown callback.
     799   *
     800   * If this function is called from unit test's main(), then g_test_dbus_down()
     801   * must be called after g_test_run().
     802   */
     803  void
     804  g_test_dbus_up (GTestDBus *self)
     805  {
     806    g_return_if_fail (G_IS_TEST_DBUS (self));
     807    g_return_if_fail (self->priv->bus_address == NULL);
     808    g_return_if_fail (!self->priv->up);
     809  
     810    start_daemon (self);
     811  
     812    g_test_dbus_unset ();
     813    g_setenv ("DBUS_SESSION_BUS_ADDRESS", self->priv->bus_address, TRUE);
     814    self->priv->up = TRUE;
     815  }
     816  
     817  
     818  /**
     819   * g_test_dbus_stop:
     820   * @self: a #GTestDBus
     821   *
     822   * Stop the session bus started by g_test_dbus_up().
     823   *
     824   * Unlike g_test_dbus_down(), this won't verify the #GDBusConnection
     825   * singleton returned by g_bus_get() or g_bus_get_sync() is destroyed. Unit
     826   * tests wanting to verify behaviour after the session bus has been stopped
     827   * can use this function but should still call g_test_dbus_down() when done.
     828   */
     829  void
     830  g_test_dbus_stop (GTestDBus *self)
     831  {
     832    g_return_if_fail (G_IS_TEST_DBUS (self));
     833    g_return_if_fail (self->priv->bus_address != NULL);
     834  
     835    stop_daemon (self);
     836  }
     837  
     838  /**
     839   * g_test_dbus_down:
     840   * @self: a #GTestDBus
     841   *
     842   * Stop the session bus started by g_test_dbus_up().
     843   *
     844   * This will wait for the singleton returned by g_bus_get() or g_bus_get_sync()
     845   * to be destroyed. This is done to ensure that the next unit test won't get a
     846   * leaked singleton from this test.
     847   */
     848  void
     849  g_test_dbus_down (GTestDBus *self)
     850  {
     851    GDBusConnection *connection;
     852  
     853    g_return_if_fail (G_IS_TEST_DBUS (self));
     854    g_return_if_fail (self->priv->up);
     855  
     856    connection = _g_bus_get_singleton_if_exists (G_BUS_TYPE_SESSION);
     857    if (connection != NULL)
     858      g_dbus_connection_set_exit_on_close (connection, FALSE);
     859  
     860    if (self->priv->bus_address != NULL)
     861      stop_daemon (self);
     862  
     863    if (connection != NULL)
     864      _g_object_unref_and_wait_weak_notify (connection);
     865  
     866    g_test_dbus_unset ();
     867    _g_bus_forget_singleton (G_BUS_TYPE_SESSION);
     868    self->priv->up = FALSE;
     869  }
     870  
     871  /**
     872   * g_test_dbus_unset:
     873   *
     874   * Unset DISPLAY and DBUS_SESSION_BUS_ADDRESS env variables to ensure the test
     875   * won't use user's session bus.
     876   *
     877   * This is useful for unit tests that want to verify behaviour when no session
     878   * bus is running. It is not necessary to call this if unit test already calls
     879   * g_test_dbus_up() before acquiring the session bus.
     880   */
     881  void
     882  g_test_dbus_unset (void)
     883  {
     884    g_unsetenv ("DISPLAY");
     885    g_unsetenv ("DBUS_SESSION_BUS_ADDRESS");
     886    g_unsetenv ("DBUS_STARTER_ADDRESS");
     887    g_unsetenv ("DBUS_STARTER_BUS_TYPE");
     888    /* avoid using XDG_RUNTIME_DIR/bus */
     889    g_unsetenv ("XDG_RUNTIME_DIR");
     890  }