cleanup
[platform/upstream/glib.git] / gio / gtestdbus.c
index e059a72..4af270b 100644 (file)
@@ -321,87 +321,75 @@ _g_test_watcher_remove_pid (GPid pid)
  * A helper class for testing code which uses D-Bus without touching the user's
  * session bus.
  *
- * Note that #GTestDBus modifies the user’s environment, calling setenv(). This
- * is not thread-safe, so all #GTestDBus calls should be completed before
+ * Note that #GTestDBus modifies the user’s environment, calling setenv().
+ * This is not thread-safe, so all #GTestDBus calls should be completed before
  * threads are spawned, or should have appropriate locking to ensure no access
  * conflicts to environment variables shared between #GTestDBus and other
  * threads.
  *
- * <refsect2 id="gio-D-Bus-Test-Scaffolding">
- *   <title>Creating unit tests using GTestDBus</title>
- *   <para>
- *     Testing of D-Bus services can be tricky because normally we only ever run
- *     D-Bus services over an existing instance of the D-Bus daemon thus we
- *     usually don't activate D-Bus services that are not yet installed into the
- *     target system. The #GTestDBus object makes this easier for us by taking care
- *     of the lower level tasks such as running a private D-Bus daemon and looking
- *     up uninstalled services in customizable locations, typically in your source code tree.
- *   </para>
- *   <para>
- *     The first thing you will need is a separate service description file for the
- *     D-Bus daemon. Typically a <filename>services</filename> subdirectory of
- *     your <filename>tests</filename> directory
- *     is a good place to put this file.
- *   </para>
- *   <para>
- *     The service file should list your service along with an absolute path to the
- *     uninstalled service executable in your source tree. Using autotools we would
- *     achieve this by adding a file such as <filename>my-server.service.in</filename>
- *     in the services
- *     directory and have it processed by configure.
- *     |[
+ * ## Creating unit tests using GTestDBus
+ * 
+ * Testing of D-Bus services can be tricky because normally we only ever run
+ * D-Bus services over an existing instance of the D-Bus daemon thus we
+ * usually don't activate D-Bus services that are not yet installed into the
+ * target system. The #GTestDBus object makes this easier for us by taking care
+ * of the lower level tasks such as running a private D-Bus daemon and looking
+ * up uninstalled services in customizable locations, typically in your source
+ * code tree.
+ *
+ * The first thing you will need is a separate service description file for the
+ * D-Bus daemon. Typically a `services` subdirectory of your `tests` directory
+ * is a good place to put this file.
+ *
+ * The service file should list your service along with an absolute path to the
+ * uninstalled service executable in your source tree. Using autotools we would
+ * achieve this by adding a file such as `my-server.service.in` in the services
+ * directory and have it processed by configure.
+ * |[
  *     [D-BUS Service]
  *     Name=org.gtk.GDBus.Examples.ObjectManager
  *     Exec=@abs_top_builddir@/gio/tests/gdbus-example-objectmanager-server
- *     ]|
- *     You will also need to indicate this service directory in your test
- *     fixtures, so you will need to pass the path while compiling your
- *     test cases. Typically this is done with autotools with an added
- *     preprocessor flag specified to compile your tests such as:
- *     |[
+ * ]|
+ * You will also need to indicate this service directory in your test
+ * fixtures, so you will need to pass the path while compiling your
+ * test cases. Typically this is done with autotools with an added
+ * preprocessor flag specified to compile your tests such as:
+ * |[
  *     -DTEST_SERVICES=\""$(abs_top_builddir)/tests/services"\"
- *     ]|
- *   </para>
- *   <para>
+ * ]|
  *     Once you have a service definition file which is local to your source tree,
- *     you can proceed to set up a GTest fixture using the #GTestDBus scaffolding.
- *       <title>Test Fixture for D-Bus services</title>
- *       <programlisting>
- *         <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-test-fixture.c">
- *           <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
- *         </xi:include>
- *       </programlisting>
- *     </example>
- *   </para>
- *   <para>
- *     Note that these examples only deal with isolating the D-Bus aspect of your
- *     service. To successfully run isolated unit tests on your service you may need
- *     some additional modifications to your test case fixture. For example; if your
- *     service uses GSettings and installs a schema then it is important that your test service
- *     not load the schema in the ordinary installed location (chances are that your service
- *     and schema files are not yet installed, or worse; there is an older version of the
- *     schema file sitting in the install location).
- *   </para>
- *   <para>
- *     Most of the time we can work around these obstacles using the environment. Since the
- *     environment is inherited by the D-Bus daemon created by #GTestDBus and then in turn
- *     inherited by any services the D-Bus daemon activates, using the setup routine for your
- *     fixture is a practical place to help sandbox your runtime environment. For the rather
- *     typical GSettings case we can work around this by setting <envar>GSETTINGS_SCHEMA_DIR</envar> to the
- *     in tree directory holding your schemas in the above fixture_setup() routine.
- *   </para>
- *   <para>
- *     The GSettings schemas need to be locally pre-compiled for this to work. This can be achieved
- *     by compiling the schemas locally as a step before running test cases, an autotools setup might
- *     do the following in the directory holding schemas:
- *     |[
+ * you can proceed to set up a GTest fixture using the #GTestDBus scaffolding.
+ *
+ * An example of a test fixture for D-Bus services can be found
+ * here:
+ * [gdbus-test-fixture.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-test-fixture.c)
+ *
+ * Note that these examples only deal with isolating the D-Bus aspect of your
+ * service. To successfully run isolated unit tests on your service you may need
+ * some additional modifications to your test case fixture. For example; if your
+ * service uses GSettings and installs a schema then it is important that your test service
+ * not load the schema in the ordinary installed location (chances are that your service
+ * and schema files are not yet installed, or worse; there is an older version of the
+ * schema file sitting in the install location).
+ *
+ * Most of the time we can work around these obstacles using the
+ * environment. Since the environment is inherited by the D-Bus daemon
+ * created by #GTestDBus and then in turn inherited by any services the
+ * D-Bus daemon activates, using the setup routine for your fixture is
+ * a practical place to help sandbox your runtime environment. For the
+ * rather typical GSettings case we can work around this by setting
+ * `GSETTINGS_SCHEMA_DIR` to the in tree directory holding your schemas
+ * in the above fixture_setup() routine.
+ *
+ * The GSettings schemas need to be locally pre-compiled for this to work. This can be achieved
+ * by compiling the schemas locally as a step before running test cases, an autotools setup might
+ * do the following in the directory holding schemas:
+ * |[
  *     all-am:
  *             $(GLIB_COMPILE_SCHEMAS) .
  *
  *     CLEANFILES += gschemas.compiled
- *     ]|
- *   </para>
- * </refsect2>
+ * ]|
  */
 
 typedef struct _GTestDBusClass   GTestDBusClass;
@@ -430,6 +418,7 @@ struct _GTestDBusPrivate
   GTestDBusFlags flags;
   GPtrArray *service_dirs;
   GPid bus_pid;
+  gint bus_stdout_fd;
   gchar *bus_address;
   gboolean up;
 };
@@ -578,13 +567,12 @@ write_config_file (GTestDBus *self)
       "  </policy>\n"
       "</busconfig>\n");
 
+  close (fd);
   g_file_set_contents (path, contents->str, contents->len, &error);
   g_assert_no_error (error);
 
   g_string_free (contents, TRUE);
 
-  close (fd);
-
   return path;
 }
 
@@ -594,8 +582,8 @@ start_daemon (GTestDBus *self)
   const gchar *argv[] = {"dbus-daemon", "--print-address", "--config-file=foo", NULL};
   gchar *config_path;
   gchar *config_arg;
-  gint stdout_fd;
   GIOChannel *channel;
+  gint stdout_fd2;
   gsize termpos;
   GError *error = NULL;
 
@@ -620,15 +608,21 @@ start_daemon (GTestDBus *self)
                             NULL,
                             &self->priv->bus_pid,
                             NULL,
-                            &stdout_fd,
+                            &self->priv->bus_stdout_fd,
                             NULL,
                             &error);
   g_assert_no_error (error);
 
   _g_test_watcher_add_pid (self->priv->bus_pid);
 
-  /* Read bus address from daemon' stdout */
-  channel = g_io_channel_unix_new (stdout_fd);
+  /* Read bus address from daemon' stdout. We have to be careful to avoid
+   * closing the FD, as it is passed to any D-Bus service activated processes,
+   * and if we close it, they will get a SIGPIPE and die when they try to write
+   * to their stdout. */
+  stdout_fd2 = dup (self->priv->bus_stdout_fd);
+  g_assert_cmpint (stdout_fd2, >=, 0);
+  channel = g_io_channel_unix_new (stdout_fd2);
+
   g_io_channel_read_line (channel, &self->priv->bus_address, NULL,
       &termpos, &error);
   g_assert_no_error (error);
@@ -672,6 +666,8 @@ stop_daemon (GTestDBus *self)
   _g_test_watcher_remove_pid (self->priv->bus_pid);
   g_spawn_close_pid (self->priv->bus_pid);
   self->priv->bus_pid = 0;
+  close (self->priv->bus_stdout_fd);
+  self->priv->bus_stdout_fd = -1;
 
   g_free (self->priv->bus_address);
   self->priv->bus_address = NULL;